首页
最新活动
服务器租用
香港服务器租用
台湾服务器租用
美国服务器租用
日本服务器租用
新加坡服务器租用
高防服务器
香港高防服务器
台湾高防服务器
美国高防服务器
裸金属
香港裸金属服务器
台湾裸金属服务器
美国裸金属服务器
日本裸金属服务器
新加坡裸金属服务器
云服务器
香港云服务器
台湾云服务器
美国云服务器
日本云服务器
CDN
CDN节点
CDN带宽
CDN防御
CDN定制
行业新闻
官方公告
香港服务器资讯
帮助文档
wp博客
zb博客
服务器资讯
联系我们
关于我们
机房介绍
机房托管
登入
注册
帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
联系客服
服务器资讯
/
香港服务器租用
/
香港VPS租用
/
香港云服务器
/
美国服务器租用
/
台湾服务器租用
/
日本服务器租用
/
官方公告
/
帮助文档
分别通过select、多进程、多线程实现一个并发服务器
发布时间:2024-03-07 17:08:10 分类:帮助文档
分别通过select、多进程、多线程实现一个并发服务器 多进程 #include
#define PORT 8888 //端口号 #define IP "192.168.114.74" //IP地址 //定义函数处理客户端信息 int deal_cli_msg(int newfd, struct sockaddr_in cin) { //5、收发数据使用newfd完成通信 char buf[128] = ""; while(1) { //清空字符串 bzero(buf, sizeof(buf)); //read(newfd, buf, sizeof(buf)); //从套接字中读取客户端发来的消息 int res = recv(newfd, buf, sizeof(buf), 0); //从套接字中读取客户端发来的消息 //buf[strlen(buf)-1] = '\0'; //判断收到的结果 if(res == 0) { printf("客户端已经下线\n"); break; }else if(res < 0) { perror("recv error"); return -1; } printf("[%s:%d]:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf); //将读取的信息,加上一些字符发送回去 strcat(buf, "*_*"); send(newfd, buf, sizeof(buf), 0); } close(newfd); //关闭通信的套接字 return 0; } //定义信号处理函数 void handler(int signo) { if(signo == SIGCHLD) { while(waitpid(-1, NULL, WNOHANG) > 0); //非阻塞形式回收僵尸进程 } } int main(int argc, const char *argv[]) { //1、创建用于接受连接的套接字 int sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd == -1) { perror("socket error"); return -1; } printf("socket success sfd = %d\n", sfd); //4 //设置端口号快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) { perror("setsockopt error"); return -1; } printf("设置端口快速重用成功 _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //2、绑定IP地址和端口号 //2.1、填充要绑定的地址信息结构体 struct sockaddr_in sin; sin.sin_family = AF_INET; //表明是ipv4 sin.sin_port = htons(PORT); //端口号 sin.sin_addr.s_addr = inet_addr(IP); //IP地址 //2.2、绑定 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1) { perror("bind error"); return -1; } printf("bind success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //3、将套接字设置成被动监听状态 if(listen(sfd, 128) == -1) { perror("listen error"); return -1; } printf("listen success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //4、阻塞等待客户端连接请求,如果有新的客户端连接,则创建一个新的用于通信的套接字 //4.1、定义客户端地址信息结构体 struct sockaddr_in cin; //客户端地址信息结构体 cin.sin_family = AF_INET; socklen_t socklen = sizeof(cin); //客户端地址信息的大小 //定义子进程变量 pid_t pid; //将SIGCHLD信号绑定到自定义信号处理函数中 if(signal(SIGCHLD, handler) == SIG_ERR) { perror("signal error"); return -1; } while(1) { //4.2、阻塞接收客户端的链接请求,并且获取客户端的地址信息 int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen); if(newfd == -1) { perror("accept error"); return -1; } printf("accept success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //创建子进程,让子进程完成通信 pid = fork(); if(pid > 0) { //关闭newfd,父进程不用 close(newfd); }else if(pid == 0) { //对于子进程而言,sfd是没有用的,需要关闭 close(sfd); //调用处理客户端函数、 deal_cli_msg(newfd, cin); //退出子进程 exit(EXIT_SUCCESS); }else { perror("fork error"); return -1; } } //6、关闭所有套接字 close(sfd); //关闭监听 return 0; } 多线程 #include
#define PORT 8888 //端口号 #define IP "192.168.114.74" //IP地址 //定义用于向线程体传参的结构体类型 struct msg_info { int newfd; struct sockaddr_in cin; }; //定义线程体函数 void *deal_cli_msg(void *arg) { //获取主线程传递的信息 int newfd = ((struct msg_info*)arg) -> newfd; struct sockaddr_in cin = ((struct msg_info*)arg) -> cin; //5、收发数据使用newfd完成通信 char buf[128] = ""; while(1) { //清空字符串 bzero(buf, sizeof(buf)); //read(newfd, buf, sizeof(buf)); //从套接字中读取客户端发来的消息 int res = recv(newfd, buf, sizeof(buf), 0); //从套接字中读取客户端发来的消息 //buf[strlen(buf)-1] = '\0'; //判断收到的结果 if(res == 0) { printf("客户端已经下线\n"); break; }else if(res < 0) { perror("recv error"); return NULL; } printf("[%s:%d]:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf); //将读取的信息,加上一些字符发送回去 strcat(buf, "*_*"); send(newfd, buf, sizeof(buf), 0); } close(newfd); //关闭通信的套接字 ptread_exit(NULL); //退出线程 } int main(int argc, const char *argv[]) { //1、创建用于接受连接的套接字 int sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd == -1) { perror("socket error"); return -1; } printf("socket success sfd = %d\n", sfd); //4 //设置端口号快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) { perror("setsockopt error"); return -1; } printf("设置端口快速重用成功 _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //2、绑定IP地址和端口号 //2.1、填充要绑定的地址信息结构体 struct sockaddr_in sin; sin.sin_family = AF_INET; //表明是ipv4 sin.sin_port = htons(PORT); //端口号 sin.sin_addr.s_addr = inet_addr(IP); //IP地址 //2.2、绑定 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1) { perror("bind error"); return -1; } printf("bind success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //3、将套接字设置成被动监听状态 if(listen(sfd, 128) == -1) { perror("listen error"); return -1; } printf("listen success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //4、阻塞等待客户端连接请求,如果有新的客户端连接,则创建一个新的用于通信的套接字 //4.1、定义客户端地址信息结构体 struct sockaddr_in cin; //客户端地址信息结构体 cin.sin_family = AF_INET; socklen_t socklen = sizeof(cin); //客户端地址信息的大小 while(1) { //4.2、阻塞接收客户端的链接请求,并且获取客户端的地址信息 int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen); if(newfd == -1) { perror("accept error"); return -1; } printf("accept success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //定义用于向线程体传参的结构体变量 struct msg_info info = {newfd, cin}; //创建分支线程用于通信 pthread_t tid; if(pthread_create(&tid, NULL, deal_cli_msg, &info) != 0) { printf("分支线程创建失败\n"); return -1; } //将该线程分离 if(pthread_detach(tid) != 0) { printf("分离失败\n"); return -1; } } //6、关闭所有套接字 close(sfd); //关闭监听 return 0; } select #include
#define PORT 8888 //端口号 #define IP "192.168.114.142" //IP地址 int main(int argc, const char *argv[]) { //1、创建用于接受连接的套接字 int sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd == -1) { perror("socket error"); return -1; } printf("socket success sfd = %d\n", sfd); //4 //设置端口号快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) { perror("setsockopt error"); return -1; } printf("设置端口快速重用成功 _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //2、绑定IP地址和端口号 //2.1、填充要绑定的地址信息结构体 struct sockaddr_in sin; sin.sin_family = AF_INET; //表明是ipv4 sin.sin_port = htons(PORT); //端口号 sin.sin_addr.s_addr = inet_addr(IP); //IP地址 //2.2、绑定 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1) { perror("bind error"); return -1; } printf("bind success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //3、将套接字设置成被动监听状态 if(listen(sfd, 128) == -1) { perror("listen error"); return -1; } printf("listen success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); //4、阻塞等待客户端连接请求,如果有新的客户端连接,则创建一个新的用于通信的套接字 //4.1、定义客户端地址信息结构体 struct sockaddr_in cin; //客户端地址信息结构体 cin.sin_family = AF_INET; socklen_t socklen = sizeof(cin); //客户端地址信息的大小 定义一个用于检测文件描述符的集合 fd_set readfds, tempfds; //在栈区定义 清空容器中的内容 FD_ZERO(&readfds); 将要检测的文件描述符放入集合中 FD_SET(sfd, &readfds); //将sfd文件描述符放入 FD_SET(0, &readfds); //将0号文件描述符放入 //定义一个容器 char buf[128] = ""; int res = 0; //接收select的返回值 int newfd = -1; //存放用于最新连接客户端的套接字 int maxfd = sfd; //定义控制select函数中最大文件描述符 struct sockaddr_in saveCin[1024]; //用于存放客户端地址信息结构体 while(1) { 将集合内容复制一份 tempfds = readfds; 使用select阻塞等待集合中的文件描述符有事件产生 res = select(maxfd+1, &tempfds, NULL, NULL, NULL); if(res == -1) { perror("select error"); return -1; }else if(res == 0) { printf("time out\n"); return -1; } //遍历所有集合中文件描述符 for(int i=0; i<=maxfd; i++) { //判断当前i是否在集合中,如果不在,直接判断下一个 if(!FD_ISSET(i, &tempfds)) { continue; } 判断sfd是否还在集合中 if( i == sfd) { //4.2、阻塞接收客户端的链接请求,并且获取客户端的地址信息 newfd = accept(sfd, (struct sockaddr*)&cin, &socklen); if(newfd == -1) { perror("accept error"); return -1; } printf("accept success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__); 将newfd放入readfds中 FD_SET(newfd , &readfds); //更新maxfd if(newfd > maxfd) { maxfd = newfd; } //将最新的客户端套接字放入数组的下标为new的位置 saveCin[newfd] = cin; printf("newfd = %d\n", newfd); }else if(i == 0 ) //判断是否是终端输入 { char buf1[128] = ""; bzero(buf, sizeof(buf)); //从终端获取数据 fgets(buf, sizeof(buf), stdin); //从终端获取数据 buf[strlen(buf)-1]='\0'; printf("触发终端输入事件:%s\n", buf); sprintf(buf1, "%s%s", "系统消息:", buf); //将数据发送给所有客户端 for(int j=4; j<=maxfd; j++) { send(j, buf1,sizeof(buf1), 0); } }else { //5、收发数据使用newfd完成通信 char buf[128] = ""; //清空字符串 bzero(buf, sizeof(buf)); int ret = recv(i, buf, sizeof(buf), 0); //从套接字中读取客户端发来的消息 //判断收到的结果 if(ret == 0) { printf("客户端已经下线\n"); close(i); //关闭通信的套接字 将当前的文件描述符从集合中删除 FD_CLR(i, &readfds); 更新maxfd for(int j=maxfd; j>=0; j--) { //判断当前的j是否在集合中,如果在,则为maxfd if(FD_ISSET(j, &readfds)) { maxfd = j; break; } } continue; //继续判断下一个 }else if(ret < 0) { perror("recv error"); return -1; } printf("[%s:%d]:%s\n", inet_ntoa(saveCin[i].sin_addr), ntohs(saveCin[i].sin_port), buf); //将读取的信息,加上一些字符发送回去 strcat(buf, "*_*"); send(i, buf, sizeof(buf), 0); } } } //6、关闭所有套接字 close(sfd); //关闭监听 return 0; }
上一篇
泾源电商服务器租用多少钱
下一篇
香港 科技 公司
相关文章
无需公网IP,在家SSH远程连接公司内网服务器「cpolar内网穿透」_1
服务器被攻打怎么办
中兴R5300 G4服务器iSAC管理员zteroot密码遗失的重置方法及IPV6地址启用设置
金蝶Apusic应用服务器 任意文件上传漏洞复现
pycharm连接远端服务器
服务器母机5个ip怎么设置
discuz后台怎么获取伪静态规则
电脑的内存怎么扩大5tb
开源超级终端工具——WindTerm
香港云服务器租用推荐
服务器租用资讯
·广东云服务有限公司怎么样
·广东云服务器怎么样
·广东锐讯网络有限公司怎么样
·广东佛山的蜗牛怎么那么大
·广东单位电话主机号怎么填写
·管家婆 花生壳怎么用
·官网域名过期要怎么办
·官网邮箱一般怎么命名
·官网网站被篡改怎么办
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价
7*24H在线售后
高可用资源,安全稳定
1v1专属客服对接
无忧退款试用保障
德讯电讯股份有限公司
电话:00886-982-263-666
台湾总部:台北市中山区建国北路一段29号3楼
香港分公司:九龙弥敦道625号雅兰商业二期906室
服务器租用
香港服务器
日本服务器
台湾服务器
美国服务器
高防服务器购买
香港高防服务器出租
台湾高防服务器租赁
美国高防服务器DDos
云服务器
香港云服务器
台湾云服务器
美国云服务器
日本云服务器
行业新闻
香港服务器租用
服务器资讯
香港云服务器
台湾服务器租用
zblog博客
香港VPS
关于我们
机房介绍
联系我们
Copyright © 1997-2024 www.hkstack.com All rights reserved.