多进程并发服务器
实现流程
	1. Socket();		创建 监听套接字 lfd2. Bind()	绑定地址结构 Strcut scokaddr_in addr;3. Listen();	4. while (1) {cfd = Accpet();			接收客户端连接请求。pid = fork();if (pid == 0){			子进程 read(cfd) --- 小写->大写 --write(cfd)			close(lfd)		关闭用于建立连接的套接字 lfdread()//小写转大写代码write()} else if (pid > 0) {	close(cfd);		关闭用于与客户端通信的套接字 cfd	continue;}}5. 子进程:close(lfd)read()小写->大写write()	父进程:close(cfd);注册信号捕捉函数:	SIGCHLD在回调函数中, 完成子进程回收while (waitpid());read 函数的返回值:1. > 0 实际读到的字节数2. = 0 已经读到结尾(对端已经关闭)【 !重 !点 !】3. -1 应进一步判断errno的值:errno = EAGAIN or EWOULDBLOCK: 设置了非阻塞方式 读。 没有数据到达。 errno = EINTR 慢速系统调用被 中断。errno = “其他情况” 异常。
代码
#include <stdio.h>  
#include <ctype.h>  
#include <stdlib.h>  
#include <sys/wait.h>  
#include <string.h>  
#include <strings.h>  
#include <unistd.h>  
#include <errno.h>  
#include <signal.h>  
#include <sys/socket.h>  
#include <arpa/inet.h>  
#include <pthread.h>  #include "wrap.h"  #define SRV_PORT 9999  void catch_child(int signum)  
{  while ((waitpid(0, NULL, WNOHANG)) > 0);  return ;  
}  int main(int argc, char *argv[])  
{  int lfd, cfd;  pid_t pid;  struct sockaddr_in srv_addr, clt_addr;  socklen_t clt_addr_len;   char buf[BUFSIZ];  int ret, i;  //memset(&srv_addr, 0, sizeof(srv_addr));                 // 将地址结构清零  bzero(&srv_addr, sizeof(srv_addr));  srv_addr.sin_family = AF_INET;  srv_addr.sin_port = htons(SRV_PORT);  srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);  lfd = Socket(AF_INET, SOCK_STREAM, 0);  Bind(lfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));  Listen(lfd, 128);  clt_addr_len = sizeof(clt_addr);  while (1) {  cfd = Accept(lfd, (struct sockaddr *)&clt_addr, &clt_addr_len);  pid = fork();  if (pid < 0) {  perr_exit("fork error");  } else if (pid == 0) {  close(lfd);  break;          } else {  struct sigaction act;  act.sa_handler = catch_child;  sigemptyset(&act.sa_mask);  act.sa_flags = 0;  ret = sigaction(SIGCHLD, &act, NULL);  if (ret != 0) {  perr_exit("sigaction error");  }  close(cfd);   continue;  }  }  if (pid == 0) {  for (;;) {  ret = Read(cfd, buf, sizeof(buf));  if (ret == 0) {  close(cfd);  exit(1);  }   for (i = 0; i < ret; i++)  buf[i] = toupper(buf[i]);  write(cfd, buf, ret);  write(STDOUT_FILENO, buf, ret);  }  }  return 0;  
}  
多线程并发服务器
实现流程
1. Socket();		创建 监听套接字 lfd2. Bind()		绑定地址结构 Strcut scokaddr_in addr;3. Listen();		4. while (1) {		cfd = Accept(lfd, );pthread_create(&tid, NULL, tfn, (void *)cfd);pthread_detach(tid);  				// pthead_join(tid, void **);  新线程---专用于回收子线程。}5. 子线程:void *tfn(void *arg) {// close(lfd)			不能关闭。 主线程要使用lfdread(cfd)小--大write(cfd)pthread_exit((void *)10);	}代码
#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...\n", ts->connfd);  break;                                              //跳出循环,关闭cfd  }  printf("received from %s at PORT %d\n",  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;  
}  2.int main(void)  
3.{  
4.    struct sockaddr_in servaddr, cliaddr;  
5.    socklen_t cliaddr_len;  
6.    int listenfd, connfd;  
7.    pthread_t tid;  
8.  
9.    struct s_info ts[256];      //创建结构体数组.  
10.    int i = 0;  
11.  
12.    listenfd = Socket(AF_INET, SOCK_STREAM, 0);                     //创建一个socket, 得到lfd  
13.  
14.    bzero(&servaddr, sizeof(servaddr));                             //地址结构清零  
15.    servaddr.sin_family = AF_INET;  
16.    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);                               //指定本地任意IP  
17.    servaddr.sin_port = htons(SERV_PORT);                                       //指定端口号   
18.  
19.    Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));             //绑定  
20.  
21.    Listen(listenfd, 128);                                                      //设置同一时刻链接服务器上限数  
22.  
23.    printf("Accepting client connect ...\n");  
24.  
25.    while (1) {  
26.        cliaddr_len = sizeof(cliaddr);  
27.        connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);   //阻塞监听客户端链接请求  
28.        ts[i].cliaddr = cliaddr;  
29.        ts[i].connfd = connfd;  
30.  
31.        pthread_create(&tid, NULL, do_work, (void*)&ts[i]);  
32.        pthread_detach(tid);                                                    //子线程分离,防止僵线程产生.  
33.        i++;  
34.    }  
35.  
36.    return 0;  
37.}