Срещал съм случай, при който използването на 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