套接字编程 (多进程多线程)

三次握手:
主动发起连接请求端,发送SYN标志位,请求建立连接。携带序号、数据字节数(0)、滑动窗口大小。
被动接受连接请求端,回复ACK标志位,同时携带 SYN 请求标志位。 携带序号、确认序号、数据字节函数(0)、滑动窗口大小
主动大气连接请求端,发送 ACK 标志位,应答服务器连接请求。携带确认序号。

四次挥手:
主动关闭连接请求端,发送 FIN标志位
被动关闭连接请求端,应答 ACK 标志位。---- 半关闭完成

被动关闭连接请求端,返送 FIN 标志位
主动关闭连接请求端,应答 ACK 标志位---- 连接全部关闭
套接字编程 (多进程多线程)
文章图片

套接字编程 (多进程多线程)
文章图片


滑动窗口:

发送给连接对端,本端缓冲区大小(实时),保证数据不会丢失

错误处理函数:

封装目的:
在server.c 编程过程中突出逻辑,将出错处理与逻辑分开,可以直接跳转man 手册

【wrap.c】【wrap.h】

存放网络通信相关 常用自定义函数函数声明

命名方式:系统调用首字母大写,方便查看man手册

如:Listen()
联合编译:

server.c 和wrap.c生成server

client.c 和 wrap.c 生成client
多进程并发服务器:
1.socket();创建 监听套接字1fd
2.bind()绑定地址结构struct sockaddr_inaddr;
3.listen();
4.while(1){
cfd = accept();接受客户端连接请求
pid=fork();
if(pid==0){
close(1fd)
read()
小 --》 大
write()
} else if (pid》0){
close(cfd);关闭与客户端通信的套接字 cfd
continue
}

}
5.子进程:
close(1fd)
read()
小 --》大
write()
父进程:
close(cfd);
注册信号捕捉函数;SIGCHLD
在回调函数中, 完成子进程的回收
while(waitpid());

//server#include #include #include #include #include #include #include #include #include#define SRV_PORT 9999 void catch_child(int signum){ (void)signum; while(waitpid(0,NULL,WNOHANG)>0); return ; }int main(){int lfd,cfd; pid_t pid; int ret,i; char buf[BUFSIZ]; char str[BUFSIZ]; struct sockaddr_in srv_addr,clt_addr; socklen_t clt_addr_len; 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); printf("receive from %s at PORT %d\n", inet_ntop(AF_INET,&clt_addr.sin_addr,str,sizeof(str)), ntohs(clt_addr.sin_port)); pid = fork(); if(pid<0){ perror("fork error"); exit(1); }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){ perror("sigaction error"); exit(1); }close(cfd); continue; }} if(pid==0){ for(; ; ){ ret = read(cfd,buf,sizeof(buf)); if(ret==0){ close(cfd); exit(1); } for(i=0; i #include #include #include#define SERV_PORT9999void sys_err(const char* str){ perror(str); exit(1); } int main(){ int cfd; char buf[BUFSIZ]; struct sockaddr_in serv_addr; //服务器地址结构serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERV_PORT); inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr.s_addr); cfd = socket(AF_INET,SOCK_STREAM,0); if(cfd==-1){ sys_err("socket error"); } int ret=connect(cfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)); if(ret!=0){ sys_err("connect error"); } while(1){ ret =read(STDIN_FILENO,buf,sizeof(buf)); write(cfd,buf,ret); ret=read(cfd,buf,sizeof(buf)); write(STDOUT_FILENO,buf,ret); sleep(1); } close(cfd); return 0; }




多线程并发服务器: server.c
1.socket()创建 监听套接字 1fd
2.bind()绑定地址结构 struct sockaddr_in addr;
3.listen()

4.while(1){

cfd = accept(1fd);
pthread_create(&tid,NULL,tfn,NULL);
pthread——detach(tid)
}

5.子线程
void* tfn(void* arg){
close(1fd)
read(cfd)
小-->大

write(cfd)
pthread_exit((void*)10);

}
#include #include #include #include #include #include #include #include#define MAXLINE 8192#define SERV_PORT 8000struct 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]; while(1){ n =read(ts->connfd,buf,MAXLINE); if(n==0){ printf("the client %d close\n",ts->connfd); break; } printf("receive from %s at PORT %d\n", inet_ntop(AF_INET,&(*ts).cliaddr.sin_addr,str,sizeof(str)), ntohs((*ts).cliaddr.sin_port)); write(STDOUT_FILENO,buf,n); for(i=0; iconnfd,buf,n); } close(ts->connfd); return (void*)0; }int main(){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); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port= htons(SERV_PORT); servaddr.sin_addr.s_addr=htonl(INADDR_ANY); bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); listen(listenfd,128); printf("accepting client connect\n"); while(1){ cliaddr_len =sizeof(cliaddr); connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddr_len); ts[i].cliaddr=cliaddr; ts[i].connfd= connfd; pthread_create(&tid,NULL,do_work,(void*)&ts[i]); pthread_detach(tid); i++; } return 0; }

【套接字编程 (多进程多线程)】

    推荐阅读