gpt4 book ai didi

c - 如果使用 Ctrl+c 关闭客户端,服务器会在 `send` 死机

转载 作者:太空狗 更新时间:2023-10-29 15:15:01 28 4
gpt4 key购买 nike

我不明白为什么这个应用程序在 send 时死掉。这是服务器的代码:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <stdlib.h>
#include <errno.h>

#define UNIX_PATH_MAX 108
#define SPATH "./sock"

int main() {
int sfd, rv = 100, newfd;
char b[100];
char ok[3] = "ok\0";
struct sockaddr_un sa;

sfd = socket(AF_UNIX, SOCK_STREAM, 0);

strncpy(sa.sun_path, SPATH, UNIX_PATH_MAX);
sa.sun_family = AF_UNIX;

if (bind(sfd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}

if (listen(sfd, SOMAXCONN) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}

if ((newfd = accept(sfd, NULL, NULL)) == -1) {
perror("accept");
exit(EXIT_FAILURE);
}

while (rv != -1 && rv != 0) {
rv = recv(newfd, b, 100, 0);

printf("%s\n", b);

sleep(3);

printf("Send reply\n");
send(newfd, ok, 3, 0);
printf("Sent reply\n");
}

printf("END\n");
}

不幸的是,如果客户端在发送消息后立即使用 Ctrl+C 强制关闭,服务器将打印(如最后一行):

发送前

然后它没有做任何其他事情就死了。我试图检查 errno 或其他任何内容(包括在 if 语句中调用 send),但似乎是 send 本身导致服务器死机。我已经尝试使用 write 但它是一样的。

我用 bash 检查了它的返回码,它以返回码 141 退出,我无法理解它的含义。

如果你想尝试,这里是客户端代码:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

#define UNIX_PATH_MAX 108
#define SPATH "./sock"

int main() {
int sfd, rv;
char b[100];
char ok[3];
struct sockaddr_un sa;

sfd = socket(AF_UNIX, SOCK_STREAM, 0);

strncpy(sa.sun_path, SPATH, UNIX_PATH_MAX);
sa.sun_family = AF_UNIX;

connect(sfd, (struct sockaddr*)&sa, sizeof(sa));

while (scanf("%s", b)) {
send(sfd, b, 100, 0);

recv(sfd, ok, 3, 0);

printf("%s\n", ok);
}

printf("END\n");
}

只需编译、运行两者,然后在消息发送后立即使用 Ctrl+C 终止客户端。

最佳答案

当您在已关闭的连接上调用 send() 时,操作系统可能会向您的进程发出 SIGPIPE。通常 SIGPIPE 的默认处理程序是终止您的进程。

为了防止这种情况发生,您可以忽略信号(例如,使用 signal(SIGPIPE, SIG_IGN)sigignore(SIGPIPE)),或者您可以将 MSG_NOSIGNAL 选项传递给 send():

int send_result = send(newfd, ok, 3, MSG_NOSIGNAL);
if (send_result >= 0) {
/* okay, but check if all your data got sent! */
if (send_result < 3) /* ...do something */;
} else {
switch (errno) {
/* ... */
case EPIPE:
/* sending on a closed connection... */
}
}

现在,send() 调用将失败,而不是发出 SIGPIPE,并且 errno 将设置为 EPIPE.

关于c - 如果使用 Ctrl+c 关闭客户端,服务器会在 `send` 死机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17332646/

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