gpt4 book ai didi

当客户端断开连接时,C 服务器停止响应

转载 作者:行者123 更新时间:2023-11-30 15:52:33 26 4
gpt4 key购买 nike

我使用 pthread 编写了一个相当简单的 C 聊天服务器。服务器工作正常,客户端使用telnet连接到服务器,然后客户端可以相互通信。每个客户端都在自己的线程中启动。当任何客户端决定断开连接时,问题就会出现。即使我关闭客户端套接字并完成其线程(它确实如此,或者至少 gdb 是这么说的),这种干扰以某种方式关闭了服务器端的所有通信,即使其他线程仍在运行。此后,客户端无法相互通信,因此服务器变得毫无用处。我不知道如何解决这个问题,我请求你的帮助。谢谢。

这是我的代码。我包含完整的代码,因为我不确定我的错误在哪里

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>

int user[30]; // sockets of connected users
char names[30][20];
int user_count=0; // number of active connections
int listen_sock; // main socket, recieves connections
char buffer[500];
pthread_t *thready[30];
pthread_mutex_t mutex;


struct arg_struct {
int arg1;
int arg2;
};

void sending(char *text, int i) {
char buffer2[504];
strcpy(buffer2, "\r\0");
strcat(buffer2, text);
strcat(buffer2, "\r\0");
write(user[i], buffer2, strlen(buffer2));
}

void welcome(int id) {
int len;
int sock;
char name[20];
pthread_mutex_lock(&mutex);
sock = user[id];

write(sock,"\rEnter your name: ", 18);
// Read returns number of characters recieved
len = read(sock,name,20);
// Add zero to the end of string (read doesnt do it)
name[len]='\0';

while (name[len] < 32)
{
name[len]='\0';
len--;
}

// snprintf(buffer,"Welcome %s!\n",name);
write(sock, "Welcome\r\n", 7);
strcpy(names[id], name);
sending(buffer,id);
pthread_mutex_unlock(&mutex);
}

void echo(char *text) {
int i;
for (i=0; i<user_count; i++) {
sending(text, i);
}
}

void disconnect(int id) {
int i;
char deadname[20];

strcpy(deadname,names[id]);
sending("You have been disconnected\n",id);
shutdown(user[id], SHUT_RDWR);
close(user[id]);
for (i=id; i<user_count-1; i++) {
user[i]=user[i+1];
strcpy(names[i],names[i+1]);
}
user_count--;
sprintf(buffer,"%s has disconnected\n",deadname);
echo(buffer);
}

void finish() {
echo("Shuting down, disconnecting everyone!\n");
while (user_count > 0) disconnect(user_count-1);
shutdown(listen_sock, SHUT_RDWR);
close(listen_sock);
pthread_mutex_destroy(&mutex);
exit(0);
}

void getcomm(char *inpstr, char *comm) { /* First letter from inpstr goes to comm,
and is removed from inpstr */
int wpos=0,leng; /* Splits first word from the rest of the sentence */
char *zal;

zal=inpstr;
leng=strlen(zal);

while (*inpstr>32 && wpos<14) {
*comm=*inpstr++;
comm++;
wpos++;
}
inpstr=(char *)memmove(zal,inpstr+1,leng);
*comm='\0';
}

void input(int id) {

}

void* communication(void* par){
int sock = ((int*)par)[0];
int id = ((int*)par)[1];
free((int*)par);
welcome(id);
while(1){
char line[500];
char command[20];
char name2[16];
int len,sock;

// 1. read line from user
len=read(user[id],line,499);
pthread_mutex_lock(&mutex);
line[len]='\0';
if (len == 0) { // User has terminated the connection
continue;
}

while (line[len] < 32) { // Remove special chars
line[len]='\0';
len--;
}

// 2. Get first word
getcomm(line,command);

// 3. Recognise command and execute it
len=strlen(command);
if (strncmp(command,"quit",4) == 0) {
disconnect(id);
pthread_exit(NULL);
}
else if (!strncmp(command,"tell",len)) {
getcomm(line,name2);
sprintf(buffer,"%s tells %s: %s\n", names[id], name2, line);
echo(buffer);
}
else if (!strncmp(command,"shut",len)) {
finish();
}
// 4. Unknown command
else {
sprintf(buffer,"%s tells %s %s\n", names[id], command, line);
echo(buffer);
}
pthread_mutex_unlock(&mutex);
}
}

int main( int argc, char *argv[] ) {
int pid;
struct sockaddr_in bind_addr;
struct sockaddr_in acc_addr;
int size, user_id, i, sel,on;
int port_number;
char * eptr = NULL;
fd_set readmask;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutex_init(&mutex, NULL);

listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sock==-1) {
perror("socket()");
pthread_mutex_destroy(&mutex);
exit(-1);
}
on = 1;
if (argc == 1){
perror("Please specify port number");
pthread_mutex_destroy(&mutex);
//exit(0);
}
if (argc == 2){
port_number = (int) strtol(argv[1], &eptr, 10);
if (*eptr != '\0'){
perror("Invalid Port Number!");
pthread_mutex_destroy(&mutex);
exit(-1);
}
}
port_number = 7501;

bind_addr.sin_family = AF_INET;
bind_addr.sin_addr.s_addr = INADDR_ANY;
bind_addr.sin_port = htons(port_number);
size=sizeof(struct sockaddr_in);
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

if (bind(listen_sock, (struct sockaddr *)&bind_addr, size)==-1) {
perror("bind()");
pthread_mutex_destroy(&mutex);
exit(-1);
}

listen(listen_sock, 10);

while(1) {
FD_ZERO(&readmask);
FD_SET(listen_sock, &readmask);
if (FD_ISSET(listen_sock, &readmask)) {
user_id = user_count++;
int * soc = (int*)malloc(2*sizeof(int));

soc[0] = accept(listen_sock,(struct sockaddr *)&acc_addr, &size);
soc[1] = user_id;
pthread_mutex_lock(&mutex);
user[user_id] = soc[0];

pthread_mutex_unlock(&mutex);

if( ( pthread_create( &thready[user_id], NULL, communication, (void*)soc ) ) < 0)
{
perror("could not create thread");
return 1;
}
echo(buffer);
continue;
}
}

pthread_mutex_destroy(&mutex);
return 0;
}

最佳答案

在调用 pthread_exit() 之前,您似乎没有解锁互斥锁。这应该会阻止所有其他通信线程。

此外,您是否错过了 FD_SET() 之后的 select() 调用?

关于当客户端断开连接时,C 服务器停止响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14344162/

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