多进程并发服务器
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<arpa/inet.h> #include<ctype.h> #include<strings.h> #include<sys/wait.h> #include"wrap.h" #define SERV_PORT 8888 #define SERV_IP "192.227.231.111" void wait_child(int sign) { while(waitpid(0,NULL,WNOHANG)>0); return ; } int main() { pid_t pid; int lfd,cfd; lfd=Socket(AF_INET,SOCK_STREAM,0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //设置端口复用
struct sockaddr_in serv_addr,clie_addr; socklen_t clie_addr_len; clie_addr_len=sizeof(clie_addr); bzero(&serv_addr,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(SERV_PORT); //serv_addr.sin_addr.s_addr=htonol(INADDR_ANY); 使用可用的ip //指定ip 用inet_pton转换 inet_pton(AF_INET,SERV_IP,&serv_addr.sin_addr.s_addr); Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)); Listen(lfd,128); char buf[BUFSIZ],buf_ip[BUFSIZ]; int n,i; while(1) { cfd=Accept(lfd,(struct sockaddr*)&clie_addr,&clie_addr_len); printf("client:%s port:%d has connected",inet_ntop(AF_INET,&clie_addr.sin_addr.s_addr,buf_ip,sizeof(buf_ip)),ntohs(clie_addr.sin_port)); pid=fork(); if(pid<0) { perror("fork err"); exit(1); }else if(pid==0) { close(lfd); break; }else{ close(cfd); signal(SIGCHLD,wait_child); } } if(pid==0) { while(1) { n=Read(cfd,buf,sizeof(buf)); if(n==0) { close(cfd); return 0;//client close }else if(n==-1) { perror("read err"); exit(1); }else{ for(i=0;i<n;i++) { buf[i]=toupper(buf[i]); } } write(cfd,buf,n); } } }
多线程并发服务器
#include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> #include <ctype.h> #include <unistd.h> #include <fcntl.h> #include "wrap.h" #define MAXLINE 8192 #define SERV_PORT 8000 struct s_info { //定义一个结构体, 将地址结构跟cfd捆绑 struct sockaddr_in cliaddr; int connfd; }; void *do_work(void *arg) { int n,i; struct s_info *ts = (struct s_info*)arg; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; //#define INET_ADDRSTRLEN 16 可用"[+d"查看 while (1) { n = Read(ts->connfd, buf, MAXLINE); //读客户端 if (n == 0) { printf("the client %d closed... ", ts->connfd); break; //跳出循环,关闭cfd } printf("received from %s at PORT %d ", inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)), ntohs((*ts).cliaddr.sin_port)); //打印客户端信息(IP/PORT) for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); //小写-->大写 Write(STDOUT_FILENO, buf, n); //写出至屏幕 Write(ts->connfd, buf, n); //回写给客户端 } Close(ts->connfd); return (void *)0; } int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; pthread_t tid; struct s_info ts[256]; //根据最大线程数创建结构体数组. int i = 0; listenfd = Socket(AF_INET, SOCK_STREAM, 0); //创建一个socket, 得到lfd bzero(&servaddr, sizeof(servaddr)); //地址结构清零 servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //指定本地任意IP servaddr.sin_port = htons(SERV_PORT); //指定端口号 8000 Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); //绑定 Listen(listenfd, 128); //设置同一时刻链接服务器上限数 printf("Accepting client connect ... "); while (1) { cliaddr_len = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //阻塞监听客户端链接请求 ts[i].cliaddr = cliaddr; ts[i].connfd = connfd; /* 达到线程最大数时,pthread_create出错处理, 增加服务器稳定性 */ pthread_create(&tid, NULL, do_work, (void*)&ts[i]); pthread_detach(tid); //子线程分离,防止僵线程产生. i++; } return 0; }