【多进程】
【多线程】
1 /************************************************************************* 2 > File summary: 多线程服务器 3 > Author: 4 > Mail: xls0930@163.com 5 > Created Time: Sun 27 Jan 2019 10:08:19 PM CST 6 ************************************************************************/ 7 8 #include<stdio.h> 9 #include<string.h> 10 #include<arpa/inet.h> 11 #include<pthread.h> 12 #include<ctype.h> 13 #include<unistd.h> 14 #include<fcntl.h> 15 16 #define MAXLINE 8192 17 #define SERV_PORT 8000 18 19 struct s_info 20 { 21 struct sockaddr_in cliaddr; 22 int connfd; 23 }; 24 25 // 回调函数 26 void *do_work(void *arg) 27 { 28 int n,i; 29 struct s_info *ts = (struct s_info *)arg; 30 char buf[MAXLINE]; 31 char str[INET_ADDRSTRLEN]; 32 33 while(1) 34 { 35 // 读出客户端的信息,关于read的返回值:返回n(n>0)表示读出n字节的数据,返回0表示已经读到结尾(可以理解为对端已关闭) 36 n = read(ts->connfd,buf,MAXLINE); 37 if(n == 0) 38 { 39 printf("the client %d close... ", ts->connfd); 40 //跳出循环 41 break; 42 } 43 //打印输出客户端的ip+port 44 printf("received from %s at PORT %d ", 45 inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr,str,sizeof(str)), 46 47 ntohs((*ts).cliaddr.sin_port)); 48 //对读出的信息进行小写转大写操作 49 for(i = 0; i < n;i++) 50 { 51 buf[i] = toupper(buf[i]); 52 } 53 // 写到服务器的标准输出 54 write(STDOUT_FILENO,buf,n); 55 // 写回客户端 56 write(ts->connfd,buf,n); 57 } 58 close(ts->connfd); 59 return (void *)0; 60 } 61 62 int main() 63 { 64 struct sockaddr_in servaddr,cliaddr; 65 socklen_t cliaddr_len; 66 int listenfd,connfd; 67 pthread_t tid; 68 69 struct s_info ts[256]; // 创建结构体数组 70 int i = 0; 71 72 listenfd = socket(AF_INET,SOCK_STREAM,0); 73 74 bzero(&servaddr, sizeof(servaddr)); 75 servaddr.sin_family = AF_INET; 76 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 77 servaddr.sin_port = htons(SERV_PORT); 78 79 bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 80 81 listen(listenfd, 128); 82 83 printf("accepting client connect ... "); 84 85 while(1) 86 { 87 cliaddr_len = sizeof(cliaddr); 88 // listenfd做监听,connfd与客户端进行读写操作,connfd中存放着客户端的信息 89 connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); 90 ts[i].cliaddr = cliaddr; 91 ts[i].connfd = connfd; 92 93 pthread_create(&tid,NULL,do_work,(void*)&ts[i]); 94 // 回收子线程 95 pthread_detach(tid); 96 i++; 97 } 98 return 0; 99 100 }
我们可以使用nc命令来模拟客户端,对代码进行测试。