为什么write()不应该返回0呢?

yoo*_*nes 1 c sockets linux broken-pipe

我遇到过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);
}
Run Code Online (Sandbox Code Playgroud)

Som*_*ude 5

write在套接字上返回零的唯一方法是让它写入零字节.如果套接字上有错误,您将永远得到-1.

如果要获得"连接关闭"指示符,则需要使用read哪个指示符返回0远程关闭连接.