为什么假定发送可能返回少于在阻塞套接字上传输的请求数据? [英] Why is it assumed that send may return with less than requested data transmitted on a blocking socket?

查看:278
本文介绍了为什么假定发送可能返回少于在阻塞套接字上传输的请求数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在流套接字上发送数据的标准方法总是调用带有一块数据的send来进行写入,检查返回值以查看是否发送了所有数据,然后继续调用send,直到整个消息接受。

The standard method to send data on a stream socket has always been to call send with a chunk of data to write, check the return value to see if all data was sent and then keep calling send again until the whole message has been accepted.

例如,这是一个常见方案的简单示例:

For example this is a simple example of a common scheme:


int send_all(int sock, unsigned char *buffer, int len) {
  int nsent;

  while(len > 0) {
    nsent = send(sock, buffer, len, 0);
    if(nsent == -1) // error
      return -1;

    buffer += nsent;
    len -= nsent;
  }
  return 0; // ok, all data sent
}

即使BSD手册页上提到

Even the BSD manpage mentions that

...如果在套接字上没有消息空间来保存要传输的消息,则send()通常阻止 ...

...If no messages space is available at the socket to hold the message to be transmitted, then send() normally blocks...

这表示我们应该假设send可以返回而不发送所有数据。现在我觉得这是相当破碎,但即使是理查德·史蒂文斯假设这在他的标准参考书中关于网络编程,而不是在开始的章节,但更高级的例子使用自己的writen(写所有数据)函数,而不是调用写。

Which indicates that we should assume that send may return without sending all data. Now I find this rather broken but even W. Richard Stevens assumes this in his standard reference book about network programming, not in the beginning chapters, but the more advanced examples uses his own writen (write all data) function instead of calling write.

现在我认为仍然要或多或少被打断,因为如果发送不能传输所有数据或接受底层缓冲区中的数据,并且套接字阻塞,则当整个发送请求被接受时发送应该阻塞并返回。

Now I consider this still to be more or less broken, since if send is not able to transmit all data or accept the data in the underlying buffer and the socket is blocking, then send should block and return when the whole send request has been accepted.

我的意思是,在上面的代码示例中,如果发送返回的数据较少,发送将会发生,它将再次调用一个新的请求。自上次通话后发生了什么变化?在最大几百个CPU周期已过,所以缓冲区仍然是满的。如果send现在接受数据为什么不能接受它之前?

I mean, in the code example above, what will happen if send returns with less data sent is that it will be called right again with a new request. What has changed since last call? At max a few hundred CPU cycles have passed so the buffer is still full. If send now accepts the data why could'nt it accept it before?

否则,我们将结束upp一个低效的循环,我们试图在套接字上发送数据不能接受数据并继续尝试,否则?

Otherwise we will end upp with an inefficient loop where we are trying to send data on a socket that cannot accept data and keep trying, or else?

所以看起来像解决方法,如果需要,导致严重低效的代码,在这些情况下应该避免阻塞套接字应该使用所有非阻塞套接字和select。

So it seems like the workaround, if needed, results in heavily inefficient code and in those circumstances blocking sockets should be avoided at all an non blocking sockets together with select should be used instead.

推荐答案

上面的描述中缺少的是Unix ,系统调用可能会被信号中断。这正是阻止 send(2)可能返回一个短计数的原因。

The thing that is missing in above description is, in Unix, system calls might get interrupted with signals. That's exactly the reason blocking send(2) might return a short count.

这篇关于为什么假定发送可能返回少于在阻塞套接字上传输的请求数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆