c# - 如何从服务器接收数据?
问题描述
我正在用 C# Windows Froms 编写一个聊天应用程序。我的问题是,我的服务器可以向每个连接的客户端发送消息,但只有发送消息的客户端才能收到响应。我试图创建一个像 ReceiveLoop() 这样的函数,里面有一个无限循环,或者添加一个计时器并为每个滴答声调用 Receive() 函数,但由于应用程序崩溃,两者都没有成功。如何实时获取数据?我附上了我客户的应用程序代码。
public partial class Form1 : Form
{
private string name;
private Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void Namebt_Click(object sender, EventArgs e)
{
if (!Test(Nametb.Text)) Nametb.Text = "Nie wpisano nazwy!";
else
{
name = Nametb.Text;
Nametb.Clear();
Nametb.Enabled = false;
Namebt.Enabled = false;
Messageslb.Enabled = true;
timer1.Start();
LoopConnect();
}
}
private void LoopConnect()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
_clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Messageslb.Items.Clear();
Messageslb.Items.Add("Connection attempts: " + attempts.ToString());
Messageslb.Refresh();
}
}
Messageslb.Items.Add("Connected!");
Messageslb.Refresh();
Messagetb.Enabled = true;
Sendbt.Enabled = true;
}
private bool Test(string text)
{
if (text != "") return true;
return false;
}
private void Sendbt_Click(object sender, EventArgs e)
{
if (!Test(Messagetb.Text)) Messagetb.Text = "Nie wpisano zadnej wiadomosci!";
else
{
Send();
}
}
private void Receive()
{
if(_clientSocket.ReceiveBufferSize > 0)
{
byte[] receivedBuffer = new byte[1024];
int rec = _clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
Messageslb.Items.Add(Encoding.ASCII.GetString(data));
}
}
private void Send()
{
string message = "[" + name + "]: " + Messagetb.Text;
Messagetb.Clear();
byte[] buffer = Encoding.ASCII.GetBytes(message);
_clientSocket.Send(buffer);
Receive();
}
private void Nametb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) Namebt_Click(sender, e);
}
private void Messagetb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) Sendbt_Click(sender, e);
}
private void timer1_Tick(object sender, EventArgs e)
{
Receive();
}
}
解决方案
您需要在单独的任务上运行接收方法。
_clientSocket.Receive(receivedBuffer);
应该:
private Task _receiving;
private void Receive()
{
if(_clientSocket.ReceiveBufferSize > 0)
{
if(_receiving == null || _receiving.IsCompleted)
_receiving = Task.Run(() =>
{
byte[] receivedBuffer = new byte[1024];
int rec = _clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
Messageslb.Items.Add(Encoding.ASCII.GetString(data));
});
}
}
否则 clientSocket.Receive 会挂起你的程序。
不过,您需要确保 Messageslb 是线程安全的,这需要进一步研究。
如果您正在寻找实时通信,请查看 C# 的 RTC 客户端https://msdn.microsoft.com/en-us/library/ms946701.aspx。否则我会强烈推荐 Socket.IO,因为它使用起来非常简单,而且设置起来非常快 rtc!https://socket.io/get-started/chat
推荐阅读
- java - 是什么导致此代码无法正确编译
- javascript - 赛普拉斯中“watchPosition”的存根
- c# - C# ASP.NET Core [Inject] 依赖注入的属性用法
- javascript - React useState 2D 数组的问题
- react-native - 包含在屏幕反应原生中的模态
- javascript - 在 aws lambda 中运行时加密验证签名失败
- python-3.x - 如何在python中链接几个散景/全息视图/面板对象的悬停?
- python - 线程 0 在使用 C 库和 Python 时崩溃
- angular - 在单个 Ionic + Angular 项目中的两个 ionic 应用程序之间导航
- python - 在 Dataframe 上将 STR 转换为 INT 不适用于特定部分