0x00 要求
![Linux平台C语言Socket编程练习之多线程服务器]()
客服端1
![Linux平台C语言Socket编程练习之多线程服务器]()
客户端2
![Linux平台C语言Socket编程练习之多线程服务器]()
0x03 心得
![Linux平台C语言Socket编程练习之多线程服务器]()
![Linux平台C语言Socket编程练习之多线程服务器]()
采用多线程并发服务器技术,服务器可以同时接受多个客户的请求。具体要求如下:
服务端 接收并显示与之连接的客户端的名称; 接收客户端发来的字符串,显示出来,并对字符串做反转处理,最后将处理后的字符串发回给客户。 客户端 根据客户输入的服务器IP地址,向服务器发起建立连接的请求; 接收客户输入的客户端名称,并把该客户端名称发给服务器; 接收客户输入的字符串,将字符串发送给服务器; 接收服务器发回的反转处理后的字符串并显示。继续接受客户输入的字符串,直到用户输入quit时退出。 0x01 代码 服务端 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <pthread.h> #define PORT 1234 #define BACKLOG 5 #define MAXDATASIZE 100 void process_cli(int connfd,struct sockaddr_in client); void* function(void* arg); struct ARG { int connfd; struct sockaddr_in client; }; int main() { int listenfd; int connfd; pthread_t tid; socklen_t client_len; struct ARG *arg; struct sockaddr_in server; struct sockaddr_in client; if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socket() failed."); exit(1); } int opt=SO_REUSEADDR; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr *)&server,sizeof(server))==-1) { perror("bind() failed."); exit(1); } if(listen(listenfd,BACKLOG)==-1) { perror("listen() failed."); exit(1); } client_len=sizeof(client); while(1) { if((connfd=accept(listenfd,(struct sockaddr *)&client,&client_len))==-1) { perror("accept() failed."); printf("runed here!\n"); exit(1); } arg=(struct ARG *)malloc(sizeof(struct ARG)); arg->connfd=connfd; memcpy((void *)&arg->client,&client,sizeof(client)); if(pthread_create(&tid,NULL,function,(void *)arg)) { perror("pthread_create() failed."); exit(1); } } close(listenfd); return 0; } void process_cli(int connfd,struct sockaddr_in client) { ssize_t send_num; ssize_t recv_num; char send_buf[MAXDATASIZE]; char recv_buf[MAXDATASIZE]; char client_name[MAXDATASIZE]; char wel_msg[]="[!] Welcome,you can input 'quit' to exit :) "; printf("[!] You got a connection from client IP: <%s> PORT: <%d> \n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); if((send(connfd,wel_msg,strlen(wel_msg),0))==-1) { perror("send welcome messages fail."); exit(1); } if((recv_num=recv(connfd,client_name,MAXDATASIZE,0))==-1) { perror("recv() failed."); close(connfd); } if(recv_num==0) { printf("[!] Client disconnected.\n"); close(connfd); } client_name[recv_num-1]='\0'; printf("[*] Client name: <%s> \n",client_name); while(1) { if((recv_num=recv(connfd,recv_buf,MAXDATASIZE,0))==-1) { perror("recv() error."); exit(1); } recv_buf[recv_num-1]='\0'; printf("[*] Received string: '%s' from client: <%s> \n ",recv_buf,client_name); size_t len=strlen(recv_buf); for(int i=0; i<(len/2); ++i) { char tmp=recv_buf[i]; recv_buf[i]=recv_buf[len-1-i]; recv_buf[len-1-i]=tmp; } strcpy(send_buf,recv_buf); printf("[>] Send reverse string: '%s' to client: <%s> \n",send_buf,client_name); if((send_num=send(connfd,send_buf,MAXDATASIZE,0))==-1) { perror("send() error."); exit(1); } if(!strcmp(send_buf,"tiuq")) { printf("[!] Client <%s> have disconnected! \n",client_name); break; } } close(connfd); } void* function(void* arg) { struct ARG *info; info=(struct ARG *)arg; process_cli(info->connfd,info->client); free(arg); pthread_exit(NULL); } 客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <netinet/in.h> #include <netdb.h> #define PORT 1234 #define MAXDATASIZE 100 int main(int argc,char *argv[]) { int sockfd; ssize_t send_num; ssize_t recv_num; char wel_msg[MAXDATASIZE]; char cli_name[MAXDATASIZE]; char recv_buf[MAXDATASIZE]; char send_buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in server; if(argc!=2) { printf("Usage:%s <IP Adress>\n",argv[0]); exit(1); } if((he=gethostbyname(argv[1]))==NULL) { printf("gethostbyname() failed."); exit(1); } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { printf("socket() failed."); exit(1); } bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr=*((struct in_addr *)he->h_addr); if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1) { printf("connect() failed."); exit(1); } if ((recv(sockfd,wel_msg,MAXDATASIZE,0))==-1) { perror("[!] Receive welcome message fail."); exit(1); } wel_msg[sizeof(wel_msg)]='\0'; printf("%s\n", wel_msg); printf("[*] Input client name:"); scanf("%s",cli_name); if((send_num=send(sockfd,cli_name,MAXDATASIZE,0))==-1) { perror("send() error."); exit(1); } while(1) { printf("[*] Input string:"); scanf("%s",send_buf); send_buf[strlen(send_buf)]='\0'; if((send_num=send(sockfd,send_buf,MAXDATASIZE,0))==-1) { perror("send() error."); exit(1); } if((recv_num=recv(sockfd,recv_buf,MAXDATASIZE,0))==-1) { perror("recv() error."); exit(1); } printf("[>] Received reverse string:%s\n",recv_buf); if(!strcmp(recv_buf,"tiuq")) { break; } } close(sockfd); return 0; } 0x02 演示 服务端
客服端1

客户端2

0x03 心得
由于pthread 库不是 linux 系统默认的库,连接时需要使用静态库 libpthread.a,不然在使用pthread_create()创建线程时会报:
undefined reference to `pthread_create'类似的错误,由于我是使用的IDE CodeBlocks,所以在Project中找到Build options,在Links setting中添加libpthread.a链接库。


如果使用gcc直接使用命令:
gcc server.c -o server -lpthread转载请注明来自4ido10n博客的 Linux平台C语言Socket编程练习之多线程服务器 ,否则保留追究文章版权的权利!