我想使用write system call在TCP套接字上编写一个填充BUFF_SIZE
字节的缓冲区:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
write()将从缓冲区指向的buf中的字节写入文件描述符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
继续发送整个缓冲区,就会发送一些冗余字节。
答案 0 :(得分:2)
如果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上讨论了 in extenso ,这是TCP / IP实现者挂出的地方,并且在那里同意,在阻塞模式下,write()
和send()
必须在返回之前发送整个缓冲区。
答案 1 :(得分:2)
查看以下函数,该函数循环write()
,直到s
的{{1}}字节被写入或发生致命错误:
b
这样称呼:
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;
}
答案 2 :(得分:1)
您需要编辑您为写入的参数编写您已发送的数据。所以像这样:
int bytes_sent = 0;
int remaining = BUFF_SIZE;
while (remaining)
{
bytes_sent = write(fd, buff, remaining);
remaining -= bytes_sent;
buff += bytes_sent;
}