我有一个服务器客户端应用程序,其中客户端将图像数据流式传输到服务器。我有以下结构:
客户端:
private void SerializeAndSendMessage(Message msg) {
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, msg);
byte[] buffer = stream.ToArray();
if (clientSocket != null)
{
if (clientSocket.Connected)
{
clientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallback, null);
}
}
}
private void SendCallback(IAsyncResult ar) {
try
{
clientSocket.EndSend(ar);
Debug.WriteLine("Message sent.");
}
catch (Exception ex)
{
//
}
}
服务器:
private void ReceiveCallback(IAsyncResult ar)
{
try
{
int received = clientSocket.EndReceive(ar);
Array.Resize(ref buffer, received);
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(buffer);
object obj = null;
stream.Position = 0;
try
{
obj = formatter.Deserialize(stream);
}
catch (Exception ex )
{
//
}
// processing data
Array.Resize(ref buffer, clientSocket.ReceiveBufferSize);
clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, null);
}
catch (Exception ex)
{
//
}
}
我期待发生的事情:
发生了什么:
这显然会导致服务器上的缓冲区填满,并且无法反序列化发送的包。我错过了什么?我可以做些什么来实现上述工作?
答案 0 :(得分:0)
TCP是一种流媒体协议。如果你在每个客户端之后在客户端进行多次发送操作,TCP会在尝试填充mtu时将它们组合成一个段。
如果mtu已满或者连续50ms计时器过去,或者客户端本身必须确认从服务器收到的数据包,TCP将发送。
TCP是一种非常复杂的协议。那里还有一个计算窗口大小的算法。此窗口大小也会影响客户端接收的段的大小。
底线是因为TCP是流协议,没有通过套接字接收的数据包的概念。您会收到任意数量的字节,您必须自己附加到某种接收缓冲区,具体取决于您正在执行的操作。如果您需要数据包,则必须使用长度字段预先添加您发送的数据,并在服务器上考虑长度。这当然使代码复杂化。或者,如果您想保持简单,只需使用UDP即可。 UDP确实支持数据包,如果数据包没有在某处丢失,你发送的内容将在接收器上以相同的大小接收。 但UDP不可靠,数据包可能会丢失。 TCP是可靠的,是面向连接的,但更复杂。
一般来说,套接字编程不是初学者话题。