我编写了一个C#聊天软件,它使用了一个新的(至少对我来说)系统,我称之为请求系统。我不知道它以前是否被创造过,但现在我认为它是我的创造。
无论如何,这个系统是这样工作的:
问题是:当我一步一步地在VS2012中工作的时候,聊天就正常了。当我在调试模式下使用它或者只是在我的桌面上运行它时,似乎缺少数据,这不应该是因为代码工作得很好.
客户端发送和接收消息的代码示例:
public void RecieveSystem()
{
while (true)
{
byte[] req = new byte[1];
soc.Receive(req);
int requestID = int.Parse(Encoding.UTF8.GetString(req));
if (requestID == 3)
{
byte[] textSize = new byte[5];
soc.Receive(textSize);
byte[] text = new byte[int.Parse(Encoding.UTF8.GetString(textSize))];
soc.Receive(text);
Dispatcher.Invoke(() => { ChatBox.Text += Encoding.UTF8.GetString(text) + "\r\n"; });
}
}
}
public void OutSystem(string inputText)
{
byte[] req = Encoding.UTF8.GetBytes("3");
soc.Send(req);
byte[] textSize = Encoding.UTF8.GetBytes(Encoding.UTF8.GetByteCount(inputText).ToString());
soc.Send(textSize);
byte[] text = Encoding.UTF8.GetBytes(inputText);
soc.Send(text);
Thread.CurrentThread.Abort();
}在服务器上:
public void UpdateChat(string text)
{
byte[] req = Encoding.UTF8.GetBytes("3");
foreach (User user in onlineUsers)
user.UserSocket.Send(req);
byte[] textSize = Encoding.UTF8.GetBytes(Encoding.UTF8.GetByteCount(text).ToString());
foreach (User user in onlineUsers)
user.UserSocket.Send(textSize);
byte[] data = Encoding.UTF8.GetBytes(text);
foreach (User user in onlineUsers)
user.UserSocket.Send(data);
}
public void RequestSystem(Socket soc)
{
~~~
}
else if (request == 3)
{
byte[] dataSize = new byte[5];
soc.Receive(dataSize);
byte[] data = new byte[int.Parse(Encoding.UTF8.GetString(dataSize))];
soc.Receive(data);
UpdateChat(Encoding.UTF8.GetString(data));
}
}
catch
{
if (!soc.Connected)
{
Dispatcher.Invoke(() => { OnlineMembers.Items.Remove(decodedName + " - " + soc.RemoteEndPoint); Status.Text += soc.RemoteEndPoint + " Has disconnected"; });
onlineUsers.Remove(user);
Thread.CurrentThread.Abort();
}
}
}
}有什么问题吗?
发布于 2014-02-24 21:57:28
您假设每个Send呼叫都有一个数据包。那不是面向流的-是面向数据包的。您正在发送多个数据片段,我怀疑这些数据被合并成一个包,然后在一个Receive调用中将它们全部获取。(即使涉及多个数据包,一个Receive调用仍然可以接收所有数据。)
如果您使用的是TCP/IP,您应该以一种更面向流的方式进行思考。我也鼓励你改变你的协议的设计,这至少可以说是奇怪的。在每条消息之前使用一个长度前缀是可以的,但是当两台计算机之间有一个完美的二进制连接时,为什么要将其编码为文本呢?
我建议您查看BinaryReader和BinaryWriter:使用TcpClient和TcpListener而不是Socket (或至少使用NetworkStream),并使用读取器/写入器对来简化数据的读取和写入(无论是有效负载还是消息长度等原语)。(BinaryWriter.Write(string)甚至为您执行长度前缀,这使事情变得更简单。)
https://stackoverflow.com/questions/21999861
复制相似问题