我无法理解为什么这个应用程序在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
强制关闭,则服务器将打印(作为最后一行):
before send
然后它没有做任何其他事情就死了。我试图检查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终止客户端。
答案 0 :(得分:12)
当您在已关闭的连接上致电send()
时,操作系统可能会向您的流程发出SIGPIPE
。通常SIGPIPE
的默认处理程序是杀死你的进程。
为了防止这种情况发生,您可以忽略该信号(例如,使用signal(SIGPIPE, SIG_IGN)
或sigignore(SIGPIPE)
),也可以将MSG_NOSIGNAL
选项传递给{{1} }:
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... */
}
}
调用将失败,而SIGPIPE
将设置为send()
,而不是发出errno
。
答案 1 :(得分:0)
在服务器端,检查客户端是否关闭了连接:
rv = recv(newfd, b, 100, 0);
if(rv<=0) {
if(!rv) {
fprintf(stderr, "conn. closed.");
} else {
perror("recv");
}
exit(EXIT_FAILURE);
}