Я столкнулся со случаем, когда использование write()
на стороне сервера на удаленно закрытом клиенте не возвращает 0.
По словам человека 2 write
:
В случае успеха возвращается количество записанных байтов (ноль означает, что ничего не было записано). При ошибке возвращается -1, и errno устанавливается соответствующим образом.
Насколько я понимаю: при использовании read
/write
на удаленно закрытом сокете первая попытка должна быть неудачной (таким образом, возвращается 0
), а следующая попытка должна вызвать сломанный канал. Но это не так. write()
действует так, как если бы ему удалось отправить данные с первой попытки, а затем я получаю сломанный канал при следующей попытке.
Мой вопрос: почему?
Я знаю, как правильно обращаться с сломанной трубой, это не проблема. Я просто пытаюсь понять, почему write
не возвращает 0
в этом случае.
Ниже приведен код сервера, который я написал. На стороне клиента я попробовал базовый клиент C (с close() и shutdown() для закрытия сокета) и netcat. Все три дали мне тот же результат.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define MY_STR "hello world!"
int start_server(int port)
{
int fd;
struct sockaddr_in sin;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
{
perror(NULL);
return (-1);
}
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1
|| listen(fd, 0) == -1)
{
perror(NULL);
close(fd);
return (-1);
}
return (fd);
}
int accept_client(int fd)
{
int client_fd;
struct sockaddr_in client_sin;
socklen_t client_addrlen;
client_addrlen = sizeof(struct sockaddr_in);
client_fd = accept(fd, (struct sockaddr *)&client_sin, &client_addrlen);
if (client_fd == -1)
return (-1);
return (client_fd);
}
int main(int argc, char **argv)
{
int fd, fd_client;
int port;
int ret;
port = 1234;
if (argc == 2)
port = atoi(argv[1]);
fd = start_server(port);
if (fd == -1)
return (EXIT_FAILURE);
printf("Server listening on port %d\n", port);
fd_client = accept_client(fd);
if (fd_client == -1)
{
close(fd);
printf("Failed to accept a client\n");
return (EXIT_FAILURE);
}
printf("Client connected!\n");
while (1)
{
getchar();
ret = write(fd_client, MY_STR, strlen(MY_STR));
printf("%d\n", ret);
if (ret < 1)
break ;
}
printf("the end.\n");
return (0);
}
write()
может возвращать число больше 0, но меньшеstrlen(MY_STR)
, а также может возвращать -1 и сигналEINTR
. - person Dietrich Epp   schedule 03.10.2015send()
, аsend()
не гарантирует доставку данных. - person Vaughn Cato   schedule 03.10.2015write
, которая запрещает когда-либо возвращать ноль, за исключением, возможно, (неуказанного) случая, когда аргумент nbyte равен нулю: pubs.opengroup.org/onlinepubs/9699919799/functions/write.html - person R.. GitHub STOP HELPING ICE   schedule 03.10.2015