gpt4 book ai didi

c - 写入关闭的套接字没有按预期引发 SIGPIPE

转载 作者:太空宇宙 更新时间:2023-11-04 03:46:31 24 4
gpt4 key购买 nike

我已经阅读了如何防止SIGPIPE,然后我写了一个小程序来测试它。这是代码。

server.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void hdl(int sig_num, siginfo_t *sig_info, void *context)
{
printf("got you, SIGPIPE!\n");
}

int main()
{
int sfd, cfd;
struct sockaddr_in saddr, caddr;


struct sigaction act;

memset (&act, '\0', sizeof(act));
act.sa_sigaction = hdl;
act.sa_flags = SA_SIGINFO;

if (sigaction(SIGPIPE, &act, NULL) < 0) {
return 1;
}

sfd= socket(AF_INET, SOCK_STREAM, 0);
saddr.sin_family=AF_INET;
saddr.sin_addr.s_addr=inet_addr("192.168.22.91");
saddr.sin_port=htons(12345);

if(bind(sfd, (struct sockaddr *)&saddr, sizeof(saddr)) )
{
printf("bind error\n");
return -1;
}
if(listen(sfd, 1))
{
printf("error\n");
return -1;
}

char buf[1024] = {0};
while(1) {
printf("Server listening...\n");
cfd=accept(sfd, (struct sockaddr *)NULL, NULL);

fcntl(cfd, F_SETFL, O_NONBLOCK);
int size = read(cfd, buf, 1024);

if(size == -1)
printf("read error\n");

sleep(2); // sleep for a while to make sure the client closed the socket

int ret;
if((ret = write(cfd, buf, strlen(buf)))<0)
{
if(errno == EPIPE)
fprintf(stderr, "SIGPIPE");
}

ret = write(cfd, buf, strlen(buf)); // write again.
printf("write return %d\n", ret);
}
close(sfd);
}

客户端.c

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <assert.h>


int main()
{
int ret, fd;
struct sockaddr_in sa_dst;
char buffer[] = "hello, world";
char rcv_buf[128] = {0};

fd = socket(AF_INET, SOCK_STREAM, 0);

memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(12345);
sa_dst.sin_addr.s_addr = inet_addr("192.168.22.91");

ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr));
if(ret != -1)
{
send(fd, buffer, strlen(buffer), 0);
close(fd);
}
return 0;
}

当我在同一台 linux 机器上运行服务器和客户端时,在服务器端,第一个 write() 返回写入的字节数,而我期望 SIGPIPE 信号,因为我关闭了客户端的套接字,第二个 write() 确实生成了一个 SIGPIPE 信号。
但是当我在另一台 linux 机器或 Windows 机器上运行客户端时(使用 Winsock 实现相同的客户端),我没有捕捉到任何 SIGPIPE 信号,第二个 write() 仍然返回 buffer 的大小。谁能告诉我发生了什么事?

最佳答案

它不可能在第一次写入时发生,原因有二:

  1. 本地主机不知道对端已经关闭套接字进行读取。已收到 FIN,但这可能只是因为对等方已关闭输出。只有 RST 会告诉它,它最早不会在下一个 I/O 中得到它。
  2. 缓冲。

请注意,您通过调用 perror() 破坏了 errno 的值,因此之后对其进行测试是无效的。

关于c - 写入关闭的套接字没有按预期引发 SIGPIPE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23911929/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com