这是调用套接字发送/接收

时间:2018-06-22 05:15:50

标签: windows sockets tcp winsock blocking

我的讨论是基于连接的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;
}

我的想法正确吗?还有其他想法吗?

2 个答案:

答案 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()而不是发送:

是的