Я делаю многопоточный чат-клиент и сервер. Клиенты отправляют текст диалога на сервер, а сервер отправляет его клиенту-отправителю и другим клиентам, но когда сервер принимает более одного клиента, первый клиент получает и отправляет данные успешно, а остальные клиенты только отправляют данные успешно не получают данных. Сервер успешно получает данные от всех клиентов. Вот код:
КЛИЕНТ:
size_t size;
pthread_t sender;
pthread_t receiver;
int socket_fd;
int socket_file_transfer= -1500;
char * nick;
void sig_handler(int signal){
printf("term signal has been caught\n");
pthread_cancel(sender);
pthread_cancel(receiver);
close(socket_fd);
printf("o socket foi fechado\n");
}
struct file_transfer {
int host_fd;
int file_fd;
char * filename;
int started;
};
void *thread_send(void * socket);
void *thread_receive(void * socket);
int main(int argc,char * argv[]){
struct sigaction sig_a;
memset(&sig_a,0,sizeof(sig_a));
sig_a.sa_handler=&sig_handler;
sigaction(SIGINT,&sig_a,NULL);
int port, n;
struct sockaddr_in server_addr;
struct hostent * server;
nick=malloc(strlen(argv[3]));
memcpy(nick,argv[3],strlen(argv[3]));
char buffer[255],buffer2[80];
port=atoi(argv[2]);
socket_fd=socket(AF_INET,SOCK_STREAM, 0);
server=gethostbyname(argv[1]);
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&server_addr.sin_addr.s_addr,server->h_length);
server_addr.sin_port=htons(port);
connect(socket_fd,(struct sockaddr *) &server_addr,sizeof(server_addr));
perror("connect:");
size=strlen(argv[3]);
//sending nick size
write(socket_fd,&size,sizeof(size_t));
//sending NICK string
write(socket_fd,argv[3],size);
char * string=malloc(60);
size=0;
bzero(buffer,255);
int* params;
params = malloc(sizeof(int));
*params=socket_fd;
printf("starting thread with socket %d\n", socket_fd);
pthread_create(&sender,NULL,&thread_send,(void*) params);
pthread_create(&receiver,NULL,&thread_receive,(void*) params);
pthread_join(receiver,NULL);
pthread_join(sender,NULL);
}
void *thread_send(void * socket){
char dialogue[270];
char buffer[255];
while(1){
printf("thread_send running\n");
read(0,buffer,255);
sprintf(dialogue,"[%s] %s",nick,buffer);
size_t size=strlen(dialogue);
write(*((int *) socket),&size,sizeof(size_t));
write(*((int *) socket),dialogue,size);
bzero(buffer,255);
bzero(buffer,255);
}
}
void *thread_receive(void * socket){
struct tm *date;
time_t tim;
size_t size=0;
char buffer[255];
while(1){
read(*((int*) socket),&size,sizeof(size_t));
perror("read size of dialogue from client socket:\n");
read(*((int *) socket),buffer,size);
perror("read dialogue from cliente socket");
tim=time(NULL);
date=localtime(&tim);
printf("[%d/%d/%d-%d:%d:%d] %s\n",date->tm_mday,date->tm_mon+1,date->tm_year-100,date->tm_hour,date->tm_min,date->tm_sec,buffer);
bzero(buffer,255);
}
}
СЕРВЕР:
struct peer {
char * nick;
int socketfd;
};
void * thread_client(void * socket);
void del_user(int fd);
int npeer=0;
struct peer peers[20];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
int main(int argc, char *argv[]){
struct sigaction s;
memset(&s,0,sizeof(s));
s.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &s, NULL);
int sockfd,newsockfd,port;
socklen_t clilen;
char buffer[255];
struct sockaddr_in serv_addr,cli_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
int n;
sockfd=socket(AF_INET,SOCK_STREAM,0);
int reuse_addr = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(int));
port=atoi(argv[1]);
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(port);
bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
listen(sockfd,5);
int fide[2];
char * token[4];
//fd_set wfds, tfds,rfds,afds,receiverfds;
int* params;
size_t size=0;
//int status;
//int newtransferfd=-1;
char mem[255];
clilen=sizeof(cli_addr);
printf("starting accept():\n");
while((newsockfd=accept(sockfd,(struct sockaddr *) &cli_addr,&clilen)) > 0){
//RECEBER O TAMANHO DA STRING
read(newsockfd,&size,sizeof(size_t));
//RECEBER A STRING
read(newsockfd,buffer,size);
//peers[npeer]=(struct peer *)malloc(sizeof(struct peer));
peers[npeer].nick=malloc(strlen(buffer));
strcpy(peers[npeer].nick,buffer);
printf("nick size: %ld\n",strlen(peers[npeer].nick));
peers[npeer].socketfd=newsockfd;
char ip[30];
getnameinfo((struct sockaddr *)&cli_addr,clilen,ip,30,NULL,0,NI_NUMERICHOST);
printf("new client accepted: %s with fd=%d, ip=%s\n",peers[npeer].nick,peers[npeer].socketfd,ip);
npeer=npeer+1;
bzero(buffer,255);
pthread_t *client=malloc(sizeof(pthread_t));
params = malloc(sizeof(int));
*params=newsockfd;
printf("starting a thread with socket fd=%d\n", newsockfd);
pthread_create(client,NULL,&thread_client,(void*) params);
pthread_detach(*client);
}
}
void * thread_client(void * socket){
int sockfd=*((int*) socket);
free(socket);
printf("starting thread with socket fd %d\n",sockfd);
size_t size;
int status=1;
char buffer[255];
while(status ){
size=0;
if(read(sockfd,&size,sizeof(size_t)) == 0) {
close(sockfd);
del_user(sockfd);
pthread_exit(NULL);
}
printf("size: %ld\n",size);
read(sockfd,buffer,size);
printf("%s\n",buffer);
if(strstr(buffer,"/exit") != NULL) {
status=0;
} else {
pthread_mutex_lock(&mutex);
for(int i=0;i<npeer;i++){
size=strlen(buffer);
//perror("erro");
printf("socketfd from peers[%d]:%d\n",i,peers[i].socketfd);
write(peers[i].socketfd,&size,sizeof(size_t));
perror("first write");
write(peers[i].socketfd,buffer,strlen(buffer));
perror("second write");
bzero(buffer,255);
}
pthread_mutex_unlock(&mutex);
}
}
close(sockfd);
del_user(sockfd);
pthread_exit(NULL);
}
void del_user(int fd){
printf("del_user(int fd) is being run\n");
int index=-1;
for(int i=0;i<npeer;i++){
if(peers[i].socketfd == fd)
index=i;
}
if(index!=-1){
for(int i=index;i<npeer;i++){
peers[i]=peers[i+1];
}
npeer=npeer-1;
printf("npeer=%d\n",npeer);
}
}
ВЫХОД:
СЕРВЕР:
$ ./server 12345
starting accept():
nick size: 7
new client accepted: client1 with fd=4, ip=127.0.0.1
starting a thread with socket fd=4
starting thread with socket fd 4
nick size: 7
new client accepted: client2 with fd=5, ip=127.0.0.1
starting a thread with socket fd=5
starting thread with socket fd 5
size: 16
[client1] hello
socketfd from peers[0]:4
first write: Success
second write: Success
socketfd from peers[1]:5
first write: Success
second write: Success
size: 16
[client2] hello
socketfd from peers[0]:4
first write: Success
second write: Success
socketfd from peers[1]:5
first write: Success
second write: Success
ПЕРВЫЙ КЛИЕНТ:
$ ./client localhost 12345 client1
connect:: Success
starting thread with socket 3
thread_send running
hello
thread_send running
read size of dialogue from client socket:
: Success
read dialogue from cliente socket: Success
[10/3/20-16:57:39] [client1] hello
read size of dialogue from client socket:
: Success
read dialogue from client socket: Success
[10/3/20-16:57:48] [client2] hello
ВТОРОЙ КЛИЕНТ:
$ ./client localhost 12345 client2
connect:: Success
starting thread with socket 3
thread_send running
read size of dialogue from client socket:
: Success
read dialogue from cliente socket: Success
[10/3/20-16:57:39]
hello
thread_send running
read size of dialogue from client socket:
: Success
read dialogue from client socket: Success
[10/3/20-16:57:48]