Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当客户端套接字在C中终止时,如何防止服务器套接字关闭?_C_Multithreading_Sockets_Client Server - Fatal编程技术网

当客户端套接字在C中终止时,如何防止服务器套接字关闭?

当客户端套接字在C中终止时,如何防止服务器套接字关闭?,c,multithreading,sockets,client-server,C,Multithreading,Sockets,Client Server,我有一个在C中使用socket的多线程客户机-服务器体系结构 客户端.c Server.c intmain(){ int server_sockfd,client_sockfd; int server_len,client_len; 服务器地址、客户端地址中的结构sockaddr\u; server\u sockfd=socket(AF\u INET,SOCK\u STREAM,0); 服务器地址.sin\u family=AF\u INET; 服务器地址sin\u addr.s\u add

我有一个在C中使用socket的多线程客户机-服务器体系结构

客户端.c

Server.c

intmain(){
int server_sockfd,client_sockfd;
int server_len,client_len;
服务器地址、客户端地址中的结构sockaddr\u;
server\u sockfd=socket(AF\u INET,SOCK\u STREAM,0);
服务器地址.sin\u family=AF\u INET;
服务器地址sin\u addr.s\u addr=inet\u addr(“127.0.0.1”);
server_address.sin_port=9734;
server\u len=sizeof(服务器地址);
绑定(服务器\u sockfd,(结构sockaddr*)和服务器\u地址,服务器\u len);
听(服务器\u sockfd,100);
而((client_sockfd=accept(server_sockfd,(struct sockaddr*)和client_地址,&client_len))){
//客户地址=sizeof(客户地址);
//client_sockfd=accept(server_sockfd,(struct sockaddr*)、client_地址和client_len);
pthread\u t sniffer\u线程;
int*new_sock=malloc(sizeof(int*);
*new_sock=客户机_sockfd;
if(pthread_create(&sniffer_thread,NULL,connection_handler,(void*)new_sock)<0)
{
perror(“无法创建线程”);
返回1;
}
printf(“分配的新线程”);
}
//关闭(服务器\u sockfd);
}
void*连接\u处理程序(void*sock){
int client_sockfd=*(int*)sock;
char-str[100];
while(1){//如果我删除这个while循环,它工作得很好
printf(“服务器等待\n”);
读取(客户_sockfd,str,100);
写入(客户_sockfd,str,100);
}
}
基本上,这个想法是让服务器持续运行,新客户机可以根据需要连接和断开连接


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

有人能告诉我我到底做错了什么吗?我不希望使用新流程或使用
select()
。它必须是多线程解决方案

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

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


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

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


一个简单的修复方法是检查
读取的返回值,如果返回值为
0
,则从线程返回而不写入。

与您的问题无关,但您的程序中存在内存泄漏。以及其他资源泄漏,因为从理论上讲,您可以创建无限多的线程,这些线程将耗尽您的所有资源。完成后,您需要加入线程。关于您的问题,您从不在任何地方检查错误或关闭的连接。如果连接关闭,则
read
将返回
0
。尝试进一步使用封闭套接字将导致错误。您也不能为null终止字符串或声明字符串足够大以容纳NUL。我将在将来重构代码以处理这些问题。现在我唯一的问题是服务器在与第一个客户端的连接关闭时终止,这似乎不是由于您刚才提到的原因,顺便说一下,
client\u len
应该在每次调用
accept
之前初始化。
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);
}
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);
}
}