Программирование сокетов домена unix
У меня есть программа сокетов домена unix, клиент пытается подключиться к серверу и отправить сообщение, когда сервер примет клиента и прочитает сообщение, он будет спать в течение 5 секунд и отправит другое сообщение. В течение 5 секунд, если я использую Ctrl+ C, чтобы убить клиента, затем сервер выйдет. Как я могу справиться с этой ситуацией? Моя программа следующим образом:
клиент:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#define INFO_SERVER_PATH "/var/info_server_path"
int create_route_client()
{
int client_fd;
int addr_len;
struct sockaddr_un server_addr;
if ((client_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
perror("create route info client socket");
return -1;
}
memset(&server_addr, 0, sizeof(struct sockaddr_un));
server_addr.sun_family = AF_LOCAL;
strcpy(server_addr.sun_path, INFO_SERVER_PATH);
addr_len = offsetof(struct sockaddr_un,sun_path) + strlen(server_addr.sun_path);
if (connect(client_fd, (struct sockaddr*)&server_addr, addr_len) < 0) {
perror("socket connect");
return -1;
}
return client_fd;
}
int main(int argc, char const *argv[])
{
char *sendline = "hello server";
char recvline[512];
int client_fd;
int nwrite;
int nread;
client_fd = create_route_client();
assert(client_fd > 0);
nwrite = write(client_fd, sendline, strlen(sendline));
if (nwrite < 0) {
perror("failed to send command to the info server");
close(client_fd);
return 1;
}
nread = read(client_fd, recvline, sizeof(recvline));
if (nread < 0) {
perror("failed to read route state");
close(client_fd);
return 1;
}
recvline[nread] = '\0';
printf("%s\n", recvline);
close(client_fd);
return 0;
}
сервер:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#define INFO_SERVER_PATH "/var/info_server_path"
int create_command_server()
{
struct sockaddr_un server_addr;
size_t addr_len;
int server_fd;
if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("create socket");
return -1;
}
unlink(INFO_SERVER_PATH);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strcpy(server_addr.sun_path, INFO_SERVER_PATH);
addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(INFO_SERVER_PATH);
if (bind(server_fd, (struct sockaddr*)&server_addr, addr_len) < 0) {
perror("socket bind");
return -1;
}
if (listen(server_fd, 1) < 0) {
perror("socket listen");
return -1;
}
return server_fd;
}
int main(int argc, char const *argv[])
{
int info_server_fd = create_command_server();
char recvline[512];
char *sendline = "hello client";
int nread;
int nwrite;
while (1) {
int info_client_fd = accept(info_server_fd, NULL, NULL);
nread = read(info_client_fd, recvline, 512);
if (nread) {
int i;
for (i = 0; i < 5; i++) {
printf("i = %d\n", i);
sleep(1);
}
nwrite = write(info_client_fd , sendline, strlen(sendline));
printf("nwrite = %d\n", nwrite);
if (nwrite < 0)
perror("failed to send to client");
}
close(info_client_fd);
}
return 0;
}
1 ответ
Трудно сказать точно без компиляции и запуска вашего кода, но я предполагаю, что вы получаете сигнал SIGPIPE из-за записи в соединение, которое было закрыто, когда вы убили клиент. Действие по умолчанию для процесса, получающего SIGPIPE, - завершить процесс.
Вы можете заблокировать сигнал SIGPIPE, используя sigprocmask(), или сообщить ядру, что вы хотите заблокировать его, проигнорировать его или зарегистрировать обработчик асинхронного сигнала для него, используя sigaction(). Затем, когда вы вызываете write(), он вернет -1 и errno будет установлен в EPIPE. См. Справочную страницу для write () http://man7.org/linux/man-pages/man2/write.2.html.
См. Справочную страницу для сигналов http://man7.org/linux/man-pages/man7/signal.7.html для получения дополнительной информации о сигналах и способах их обработки. Но имейте в виду, что обработка сигналов не должна выполняться с использованием асинхронного обработчика сигналов, если вы не очень осторожны и точно не знаете, что делаете. Это источник многих ошибок. Безопаснее всего (на данный момент) игнорировать их, если они вам не нужны, или заблокировать их и использовать подход синхронной обработки сигналов, такой как sigwait() или fd (специфичный для Linux). В вашем случае они вам не нужны. Вызов write () сообщит вам, когда соединение исчезнет.