网络编程下关于服务器模型的总结
来源:互联网 发布:c语言转汇编 编辑:程序博客网 时间:2024/05/24 01:41
LINUX下关于服务器模型的总结
服务器分为1:循环服务器
2:并发服务器
循环服务器:在同一时刻只能响应一个客户端的请求。
并发服务器:在同一时刻可以响应多个客户端的请求。
在循环服务器中,分为TCP服务器和 UDP服务器,循环服务器一般很少使用。
在并发服务器中,一般有多进程并发服务器,多线程服务器,IO多路复用并发服务器。
(1)多进程的并发服务器
只要有客户端连接服务器,服务器就创建子进程与客户端通信创建子进程后,父进程—-继续等待其他客户端的连接,子进程—-与客户端通信。这样就实现了多个客户端连接服务器的要求。特点:多进程服务器,比较浪费资源,适合于客户端数量较少,但是长连接的情况
(2)多线程的并发服务器
只要有客户端连接服务器,服务器就创建子线程与客户端通信
由于在创建子线程时,以及xian毁子线程时,比较浪费时间,一般可以使用线程池多线程存在的问题:存在资源竞争以及同步的问题
特点:适用于客户端较少,但是长时间连接的情况
(3)IO多路复用的并发服务器
适合于客户端数量较多,但是短连接的情况
代码具体实现多进程的并发服务器,process_server.c
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <unistd.h>#include <pthread.h>#include <signal.h>#include <sys/wait.h>#include <stdlib.h>void signfun(int sigNo);int main(){ //定义Internet协议结构,服务器的端口号和IP地址 struct sockaddr_in myaddr; memset(&myaddr,0,sizeof(myaddr)); myaddr.sin_family = PF_INET; myaddr.sin_port = htons(1314); myaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //1.创建套接字 int serverId = socket(PF_INET,SOCK_STREAM,0); if(serverId<0) { perror("serverFd\n"); return -1; } printf("socket ok\n"); //使用setsockopt防止使用地址错误 int on=1; int set=setsockopt(serverId,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); if(set<0) { printf("setsockopt\n"); return -1; } //2.绑定地址信息 int ret = bind(serverId,(struct sockaddr *)&myaddr,sizeof(myaddr)); if(ret<0) { perror("bind\n"); close(serverId); return -1; } printf("bind ok\n"); //3.创建一个监听队列 if(listen(serverId,10)<0) { perror("listen\n"); close(serverId); return -1; } printf("listening....\n"); //4.接受链接请求 while(1) { printf("服务器正常工作中。。。\n"); int conId=accept(serverId,NULL,NULL);//接收链接 if(conId<0) { perror("accept\n"); close(serverId); return -1; } printf("accept ok\n"); pid_t pid; if((pid=fork())<0)//创建子进程处理链接请求,父进程继续监听 { perror("fock\n"); close(serverId); close (conId); return -1; } else if(pid==0) //子进程里处理聊天 { close(serverId); while(1) { char buf[1024]; memset(buf,0,1024); int ret = recv(conId,buf,sizeof(buf),0); if(ret<0) { perror("recv\n"); break; } if(ret ==0) { printf("对方下线\n"); break; } printf("from xldclient:%s\n",buf); printf("xldserver:"); gets(buf); if(strcmp(buf,"quit")==0) { break; } ret = send(conId,buf,sizeof(buf),0); if(ret <0) { perror("send\n"); break; } } close(conId);//关闭链接套接字 exit(0); //进程退出 } else { close(conId); signal(SIGCHLD,signfun);//信号处理函数, //子进程结束时会给父进程发送SIGCHLD } } //6.关闭套接字 close(serverId); return 0;}void signfun(int sigNo){ if(sigNo == SIGCHLD) { wait(NULL); } printf("子进程已结束\n");}
多线程的并发服务器具体代码,pthread_server.c
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <unistd.h>#include <pthread.h>void *profunC(void *arg);//线程处理函数的声明int main(){ //定义Internet协议结构,服务器的端口号和IP地址 struct sockaddr_in myaddr; memset(&myaddr,0,sizeof(myaddr)); myaddr.sin_family = PF_INET; myaddr.sin_port = htons(1314); myaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //1.创建套接字 int serverId = socket(PF_INET,SOCK_STREAM,0); if(serverId<0) { perror("serverFd\n"); return -1; } printf("socket ok\n"); //2.绑定地址信息 int ret = bind(serverId,(struct sockaddr *)&myaddr,sizeof(myaddr)); if(ret<0) { perror("bind\n"); close(serverId); return -1; } printf("bind ok\n"); //3.创建一个监听队列 if(listen(serverId,10)<0) { perror("listen\n"); close(serverId); return -1; } printf("listening....\n"); //4.接受链接请求 while(1) { printf("服务器正常工作中。。。\n"); int conId=accept(serverId,NULL,NULL); if(conId<0) { perror("accept\n"); close(serverId); return -1; } printf("accept ok\n"); pthread_t th1;//主线程继续等待链接 while(pthread_create(&th1,NULL,profunC,&conId)<0); } //6.关闭套接字 close(serverId); return 0;}void *profunC(void *arg){ int conId=*(int *)arg; //子线程完成通信 while(1) { char buf[1024]; memset(buf,0,1024); int ret = recv(conId,buf,sizeof(buf),0); if(ret<0) { perror("recv\n"); break; } if(ret ==0) { printf("对方下线\n"); break; } printf("from xldclient:%s\n",buf); printf("xldserver:"); gets(buf); if(strcmp(buf,"quit")==0) { break; } ret = send(conId,buf,sizeof(buf),0); if(ret <0) { perror("send\n"); break; } } close(conId); pthread_exit(NULL);}
io多路复用的并发服务器的具体代码实现io_server.c
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <arpa/inet.h>#include <unistd.h>#include <sys/time.h>#include <netinet/in.h>int main(){ //定义Internet协议结构,服务器的端口号和IP地址 struct sockaddr_in myaddr; memset(&myaddr,0,sizeof(myaddr)); myaddr.sin_family = PF_INET; myaddr.sin_port = htons(1314); myaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //1.创建套接字 int serverId = socket(PF_INET,SOCK_STREAM,0); if(serverId<0) { perror("serverFd\n"); return -1; } printf("socket ok\n"); //设置套接字选项避免地址使用错误 int on=1; int st=setsockopt(serverId,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); if(st<0) { perror("setsockopt error\n"); close(serverId); return -1; } //2.绑定地址信息 int ret = bind(serverId,(struct sockaddr *)&myaddr,sizeof(myaddr)); if(ret<0) { perror("bind\n"); close(serverId); return -1; } printf("bind ok\n"); //3.创建一个监听队列 if(listen(serverId,10)<0) { perror("listen\n"); close(serverId); return -1; } printf("listening....\n"); //1创建集合 fd_set sebuf; //2清空集合 FD_ZERO(&sebuf); //3将对应的文件描述符加入集合 FD_SET(0,&sebuf); FD_SET(1,&sebuf); FD_SET(serverId,&sebuf); int maxfd=serverId; //使用seclect监视 fd_set tmp ; int i; while(1) { printf("before select\n"); tmp = sebuf; //select监视文件的变化 int retu1=select(maxfd+1,&tmp,NULL,NULL,NULL); printf("retu1=%d\n",retu1); if(retu1<0) { perror("seclect\n"); close(serverId); return -1; } for(i=0;i<=maxfd;i++) { if(FD_ISSET(i,&tmp)) { if(i==0) { printf("stdin\n"); char buf[1024]={0}; gets(buf); printf("from stdin %s\n",buf); } else if(i==1) { printf("stdout\n"); } else if(i==serverId) { //4.接受链接请求 int conId=accept(serverId,NULL,NULL); if(conId<0) { perror("accept\n"); close(serverId); return -1; } printf("accept ok\n"); FD_SET(conId,&sebuf); if(conId > maxfd) { maxfd = conId; } } else //5.收发消息 { char buf[1024]; memset(buf,0,1024); ret = recv(i,buf,sizeof(buf),0); if(ret<0) { perror("recv\n"); close(i); return -1; } if(ret==0) { printf("对方已下线\n"); close(i); FD_CLR(i,&sebuf); continue; } printf("from xldclient:%s\n",buf); memset(buf,0,1024); printf("xldserver:"); gets(buf); ret = send(i,buf,sizeof(buf),0); if(ret <0) { perror("send\n"); close(i); return -1; } } } } } //6.关闭套接字 close(serverId); return 0;}
代码写得略有粗糙,继续努力吧。
阅读全文
1 0
- 网络编程下关于服务器模型的总结
- Linux下关于网络设置的文件
- Linux 下关于网络的几个命令
- 网络编程的服务器模型
- linux下关于网络的相关指令网络(持续中)
- Linux系统下关于网络ip地址的配置方法
- linux下关于网络配置(永久性的)
- XP下关于快速切换用户功能的相关编程
- Linux下关于时间概念的C语言编程
- Linux下关于时间概念的C语言编程
- Linux下关于时间概念的C语言编程
- Linux下关于vim编辑器的使用进行编程
- Linux下关于结构体对齐的总结
- Linux下关于结构体对齐的总结
- linux下关于调用动态库的一些总结
- linux下关于vim的一些小知识点总结
- 【Tomcat】Linux下关于Tomcat部署项目的问题总结
- 服务器网络编程模型
- Android_图片加载框架---ImageLoader
- php常用函数(数组)
- 每个人都能做的网易云音乐[vue全家桶]
- CillyB盖房子 QDU
- 运算符优先级详解
- 网络编程下关于服务器模型的总结
- 偏序集相关定理
- 如何选择一个技术解决方案
- thinkphp3.2 layout 模板布局 路径问题
- Java list.romve方法bug
- jquery换一批的写法
- vue2.0之axios使用详解(一)
- wordpress日常优化
- 【Linux Kernel 进程管理】深入分析fork