【问题标题】:How to prevent server socket from closing when client socket is terminated in C?当客户端套接字在C中终止时,如何防止服务器套接字关闭?
【发布时间】:2017-03-07 13:21:36
【问题描述】:

我有一个在 C 中使用套接字的多线程客户端-服务器架构。

Client.c

sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr=inet_addr("127.0.0.1");
address.sin_port = 9734;
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result==-1) {
    perror("oops: client1");
    return 1;
}

while(1) {
    printf("Enter a string: ");
    scanf("%s", str);
    if(strcmp(str,"exit") == 0) close(sockfd); //At this point server terminates
    write(sockfd, str, 100);
    read(sockfd, str, 100);
    printf("from server = %s\n", str);
}

Server.c

int main() {
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address, client_address;

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = 9734;
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 100);

while( (client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_address, &client_len)) ) {
    // client_len = sizeof(client_address);
    // client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_address, &client_len);
    pthread_t sniffer_thread;
    int *new_sock = malloc(sizeof(int *));
    *new_sock = client_sockfd;

    if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0)
    {
        perror("could not create thread");
        return 1;
    }
    printf("New thread assigned\n");
    }
// close(server_sockfd);
}

void *connection_handler(void *sock) {
int client_sockfd = *(int *)sock;
char str[100];
while(1) { // If I remove this while loop, it works fine
    printf("server waiting\n");
    read(client_sockfd, str, 100);
    write(client_sockfd, str, 100);
}
}

基本上这个想法是让服务器连续运行,新客户端可以根据需要连接和断开连接。


问题在于,一旦客户端被Ctrl+C 中断或发送“退出”消息,客户端就会终止,但服务器也会终止。服务器不应终止,而是侦听大多数传入的套接字请求。

有人可以就我到底做错了什么提供一些指导吗?我不希望分叉新进程或使用select()。它必须是多线程解决方案。

更新: 我对代码进行了一些更改,主要是添加了更多错误检查等。如果我在server.c 中删除线程连接处理程序中的while 循环,则服务器不会与客户端终止,这正是我想要的。但是我不想删除while循环,因为这意味着服务器和客户端只能在套接字自动关闭之前发送一条消息。

【问题讨论】:

  • 与您的问题无关,但您的程序中存在内存泄漏。以及其他资源泄漏,因为理论上您可以创建无限数量的线程,这些线程将耗尽您的所有资源。完成后,您需要加入线程。
  • 关于您的问题,您永远不会在任何地方检查错误或关闭的连接。如果连接关闭,则read 将返回0。尝试进一步使用关闭的套接字会导致错误。
  • 您也没有以空值终止您的字符串或声明它们足够大以适应 NUL。
  • 我将来会重构代码来处理这些问题。现在我唯一的问题是当与第一个客户端的连接关闭时服务器终止,由于你提到的原因,这似乎没有发生
  • 顺便说一下,client_len 应该在每次调用 accept 之前初始化。

标签: c multithreading sockets client-server


【解决方案1】:

服务器崩溃,因为连接处理程序无法识别客户端断开连接,并尝试在另一端关闭的情况下写入套接字。这导致SIGPIPE,默认操作是终止整个进程。

一个简单的解决方法是检查read的返回值,如果是0,不写就直接从线程返回。

【讨论】:

    【解决方案2】:

    您似乎认为客户端套接字(accept() 返回的那个)与服务器的原始套接字相同,即您正在侦听的那个。

    这不是真的,因为accept() 创建了一个专用于该客户端的新套接字,并连接到客户端。一旦客户端离开,这个套接字就没有用了,它应该被关闭。这不会影响您的服务器接受更多连接的能力。

    【讨论】:

      猜你喜欢
      • 2018-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2015-04-07
      • 2012-02-08
      相关资源
      最近更新 更多