我的客户端服务器应用程序使用此MSDN article提供的基本实现。但是,变化之处在于我没有使用分隔符的<EOF>
类型,因为我的应用程序的工作方式是这样的:
该循环一直持续到关闭连接为止。
引用this SO question,是否有可能通过任何从套接字接收数据的.NET实现(Socket.Receive,TCP.GetStream()。Read(...)...等)来实现读取或接收操作将返回错误的
0
的时间吗? (例如,某些数据已被读取,下一个数据包暂时卡在流量中,并且“读/接收”操作不知道,因此它只是假设没有其他要读取的内容,并且仅返回零)。我的代码如下:
public void recieveClientData()
{
byte[] bs = new byte[1];// 'commStream' is NetworkStream of the socket
commStream.Read(bs, 0, 1);//blocks until something comes in
// Buffer for reading data
Byte[] bytes = new Byte[1024];
using (MemoryStream m = new MemoryStream())
{
//scoop what we have yet
m.Write(bs, 0, 1);
//get the remaining
int length;
while ((length = commStream.Read(bytes, 0, bytes.Length)) != 0)
{
m.Write(bytes, 0, length);
}
//At this point, 'm' is sent for asyncronously processing
...
//wait for another data from this client
recieveClientData();
}
}
现在,在
while ((length = commStream.Read(bytes, 0, bytes.Length)) != 0)
行,我们假设客户端向服务器发送了一个大约32Mb的PDF文件(以便服务器可以将其保存以备将来检索),是否可能在循环,网络滞后会阻止该流读取某些内容,从而返回commStream.Read(bytes, 0, bytes.Length)
(这意味着网络数据包存在某种网络延迟,但在该数据包最终通过并被传输之前,0
已经读取commStream.Read
并返回)请注意,在这里我不能使用定界符,因为传输的数据并不总是字符串。
最佳答案
TCP连接是面向流的。没有消息的概念。因此,很有可能(至少在不良网络上),您的Write()
之一将与多个Read()
一起接收,或者多个Write()
将与一个Read()
一起被接收。您绝对不应依靠Read()
在消息/请求中中断流。
通常的方法是事先知道您将收到什么,或者在未知大小的实际数据之前发送大小。使用TCP,可以确保数据传输不被破坏,因此您应该依靠它。当然,总会发生一个大问题并重置连接,但是您将遇到一个异常,并单独进行处理。
您应该看一下BinaryReader
和BinaryWriter
,这些类可能会使您更简单:ReadString()
将读取完整的字符串,而ReadBytes()
将读取指定的字节数。
编辑:为了澄清一点,不保证以64作为大小参数的Socket.Receive()
和NetworkStream.Read()
返回64字节。它们可以返回1、10、32、63或其他值(不是0,除非有超时,否则它将一直阻塞)。另一方面,BinaryReader.ReadBytes(64)
保证等待64个字节。连接问题将单独处理,但有异常(exception)。