C语言 使用write()系统调用写入一个完整的缓冲区



我想通过TCP套接字使用写系统调用写一个充满BUFF_SIZE字节的缓冲区:

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

文档说明

write()将从指向的缓冲区写入到文件描述符fd所引用的文件,直到字节数。

当然,写入的实际字节的数量可以通过返回值来检测。然而,如果我想确保我的整个字节缓冲区通过连接发送,那么什么是一个好的方法呢?到目前为止,我在想:

while ( (ch = fgetc(pipe) ) != EOF )
{
    buff[ 0 ] = ch;
    bytes_in_buff++;
    // fill a buffer's worth of data from the pipe
    for (int i = 1; i < BUFF_SIZE; ++i, ++bytes_in_buff)
    {
        if ( (ch = fgetc(pipe) ) == EOF)
            break;
        buff[ i ] = ch;
    }
    // write that buffer to the pipe
    int bytes_sent = 0;
    while (bytes_sent < BUFF_SIZE)
    {
        bytes_sent = write(fd, buff, bytes_in_buff);
    }
}

但是,当然,如果我继续每次发送整个缓冲区,一些多余的字节将被发送bytes_sent < BUFF_SIZE

看一下下面的函数,它在write()周围循环,直到从b写入s字节或发生致命错误:

int writen(const int sd, const char * b, const size_t s, const int retry_on_interrupt)
{
  size_t n = s;
  while (0 < n)
  {
    ssize_t result = write(sd, b, n);
    if (-1 == result)
    {
      if ((retry_on_interrupt && (errno == EINTR)) || (errno == EWOULDBLOCK) || (errno == EAGAIN))
      {
        continue;
      }
      else
      {
        break;
      }
    }
    n -= result;
    b += result;
  }
  return (0 < n) ?-1 :0;
}

这样写:

int retry_on_interrupt = ... /* {0|1} depending on wether a signal reception shall abort the write operation or not. */
int result = writen(fd, buff, sizeof(buf), retry_on_interrupt)
if (-1 == result)
{
  perror("writen()");
}

如果write()的返回值小于BUFF_SIZE,建议的循环将永远不会终止;你需要检查是否有错误。

你需要这样写:

while (bytes_in_buff > 0)
{
    bytes_sent = write(fd, buff, bytes_in_buff);
    if (bytes_sent < 0)
    {
        perror("write");  // or whatever
        break;
    }
    buff += bytes_sent;
    bytes_in_buff -= bytes_sent;
}

然而这个问题已经在news:comp.protocols上广泛讨论过。TCP - IP在几年前,这是TCP/IP实实者的地方,在那里达成了协议,在阻塞模式下,write()send()必须在返回之前发送整个缓冲区。

您需要编辑您为写入提供的参数,以说明您已经发送的数据。像这样:

int bytes_sent = 0;
int remaining = BUFF_SIZE;
while (remaining) 
{
  bytes_sent = write(fd, buff, remaining);
  remaining -= bytes_sent;
  buff += bytes_sent;
}

相关内容

最新更新