我的讨论是基于连接的TCP,阻塞套接字,同步的。
首先关于Receive()
,MSDN说:
如果没有数据可读取,则
Receive()
方法将阻塞直到数据可用。如果您使用的是面向连接的Socket,则Receive()
方法将读取尽可能多的数据。直到缓冲区的大小。
对封锁的强调使我误解了这段话。后来我做了实验,得出以下结论:如果我想接受10个字节,但是套接字缓存中只能读取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;
}
我的想法正确吗?还有其他想法吗?
答案 0 :(得分:1)
如果我想接受10个字节,但是套接字缓存中只能读取6个字节,
套接字接收缓冲区。
...一次调用
Receive()
不会阻塞,直到可以读取10个字节为止。仅返回,而将尽可能多地读取现在可读的字节,即将返回6个字节,因此实际读取的字节数由返回值Receive()
表示。
正确。
因此,如果我想准确接收指定的字节,我应该呼叫
recvToCnt()
而不是Receive()
。
您当然应该循环调用Receive()
,直到获得所需的所有数据,或者发生错误或流结束,但是您发布的代码将完全忽略错误和流结束,这不是可以接受的。您需要解决该问题。
然后,我们来看看
Send()
。 ...我怀疑此描述的准确性,
不要。是正确的,处于阻止模式。
由于
Send()
也有返回值,我想它应该与Receive()
具有类似的阻塞概念。
不。在非阻塞模式下,返回值变得很重要。在阻止模式下,它的行为如上所述。
因此,如果我想确保将指定数量的字节发送到套接字缓存中,我应该使用
sendToCnt()
而不是发送
套接字发送缓冲区,否,再次,您发布的代码将忽略错误,这再次是不可接受的。
答案 1 :(得分:1)
如果我想接受10个字节,但是套接字缓存中只能读取6个字节,则一次调用
Receive()
不会阻塞,直到可以读取10个字节为止。仅返回,而将尽可能多地读取现在可读的字节,即将返回6个字节,因此实际读取的字节数由返回值Receive()
表示。
是的
因此,如果我想准确接收指定数量的字节,我应该呼叫
recvToCnt()
而不是Receive()
。
是的
我怀疑此描述的准确性,因为
Send()
也有返回值,我想它应该具有与Receive()
类似的阻塞概念。
是的。如果套接字的内核缓冲区有足够的空间来容纳至少 1个字节,但没有足够的空间来容纳所有 all ,则它可以返回的字节数少于请求的字节数发送的字节数。
因此,如果我想确保将指定数量的字节发送到套接字缓存中,我应该使用
sendToCnt()
而不是发送:
是的