我写了一个C#聊天软件,它使用了一个我称之为请求系统的新系统(至少对我而言)。我不知道之前是否已创建过,但现在我认为它是我的创作:P
无论如何,这个系统的工作原理如下:
问题是这样的:当我在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();
}
}
}
}
可能是什么问题?
答案 0 :(得分:4)
您假设每个Send
电话都有一个数据包。这不是面向流的 - 这是面向数据包的。您发送的多个数据我怀疑是合并到一个数据包中,然后您将在一次Receive
调用中获取所有这些数据。 (即使涉及多个数据包,单个Receive
呼叫仍然可以接收所有数据。)
如果您正在使用TCP / IP,那么您应该考虑采用更加面向流的方式。我也鼓励你改变协议的设计,这至少可以说是奇怪的。在每条消息之前使用长度前缀是很好的,但是当你在两台计算机之间有完美的二进制连接时,为什么要将它编码为文本呢?
我建议您查看BinaryReader
和BinaryWriter
:使用TcpClient
和TcpListener
而不是Socket
(或至少使用NetworkStream
) ,并使用读/写器对使其更容易读取和写入数据(有效载荷或基元,如消息的长度)。 (BinaryWriter.Write(string)
甚至为您执行长度前缀,这使事情变得更容易。)