【发布时间】:2018-12-01 12:39:22
【问题描述】:
我的讨论基于连接的 TCP、阻塞套接字、同步。
首先关于Receive(),MSDN 说:
如果没有数据可供读取,
Receive()方法将阻塞直到数据可用。如果您使用面向连接的 Socket,Receive()方法将读取尽可能多的数据缓冲区。
对阻塞的强调让我误解了这段话。后来我做了实验,得出如下结论:如果我想接受10个字节,但是socket缓存中只有6个字节可读,那么调用Receive()一次不会阻塞,直到10个字节可读。只是返回,而是尽可能的读取现在可读的字节,也就是会返回6个字节,所以实际读取的字节数用Receive()的返回值来表示。所以我想如果我想准确接收指定的字节数,我应该调用recvToCnt() 而不是Receive()。
private int recvToCnt(Socket socket, byte[] buf, int beginIndex, int cnt)
{
if (buf.Length < beginIndex + cnt)
return 0;
int realCnt = 0;
while (realCnt < cnt)
{
realCnt += socket.Receive(buf, beginIndex + realCnt, cnt - realCnt, SocketFlags.None);
}
return realCnt;
}
那么,让我们看看Send()。 MSDN 说:
如果您使用面向连接的协议,
Send()将阻塞,直到缓冲区中的所有字节都发送完毕,除非使用Socket.SendTimeout()设置了超时。
我怀疑这个描述的准确性,因为Send()也有返回值,我猜应该和Receive()有类似的阻塞概念。所以我想如果我想确保将指定的字节数发送到套接字缓存中,我应该使用sendToCnt() 而不是发送:
private int sendToCnt(Socket socket, byte[] buf, int beginIndex, int cnt)
{
if (buf.Length < beginIndex + cnt)
return 0;
int realCnt = 0;
while (realCnt < cnt)
{
realCnt += socket.Send(buf, beginIndex + realCnt, cnt - realCnt, SocketFlags.None);
}
return realCnt;
}
我的想法正确吗?还有什么想法吗?
【问题讨论】:
-
如果对方关闭连接或出现错误,您的
recvToCnt代码将无限循环。 -
@DavidSchwartz 如果发生错误,则会引发异常。但是你对对方关闭连接是正确的。代码需要处理
Receive()返回0表示连接已经正常关闭的情况。
标签: windows sockets tcp winsock blocking