使用write()系统调用编写完整缓冲区

我想使用write系统调用在TCP套接字上写一个填充BUFF_SIZE字节的缓冲区:

 #include  ssize_t write(int fd, const void *buf, size_t count); 

文件说明了这一点

write()写入从缓冲区指向buf的count个字节到文件描述符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()直到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_sent < BUFF_SIZE) { 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; } 

然而,这个问题几年前的新闻: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; }