当前位置: 首页 > news >正文

网络编程day3

进程与线程实现TCP并发服务器

多进程服务器端

#include<myhead.h>#define  SER_PORT  8888        //服务器端口号
#define SER_IP  "192.168.109.125"   //服务器IP地址 //定义一个信号处理函数,用于处理SIGCHLD信号
void handler(int signo)
{//判断是哪个信号到位if(signo == SIGCHLD){//说明有子进程牺牲了//使用非阻塞的形式循环回收子进程资源while(waitpid(-1, NULL, WNOHANG) > 0);}
}int main(int argc, const char *argv[])
{//将子进程向父进程发送的SIGCHLD信号,绑定到信号处理函数中if(signal(SIGCHLD, handler) == SIG_ERR){perror("signal error");return -1;}//1、创建一个用于连接的套接字文件描述符int sfd  = socket(AF_INET, SOCK_STREAM, 0);if(-1 == sfd){perror("socket  error");return -1;}printf("socket 成功 sfd = %d\n", sfd);          //3//设置套接字属性:允许端口号快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、给套接字绑定ip地址和端口号//2.1 封装地址信息结构体变量struct sockaddr_in sin;        //地址信息结构体变量sin.sin_family = AF_INET;      //通信域地址族sin.sin_port = htons(SER_PORT);   //端口号网络字节序sin.sin_addr.s_addr = inet_addr(SER_IP);  //ip地址网络字节序//2.2  绑定操作if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) ==-1){perror("bind  error");return -1;}printf("bind success\n");//3、将套接字启动监听if(listen(sfd, 128) == -1){perror("listen  error");return -1;}printf("listen success\n");//4、阻塞等等客户端的连接,如果有新客户端连接,//则创建一个用于通信的套接字struct sockaddr_in cin;            //用于接受客户端套接字信息socklen_t addrlen = sizeof(cin);   //用于接受客户端套接字的长度while(1)              //循环处理多个客户端{//接收新的客户端的连接请求int new_fd = accept(sfd, (struct sockaddr*)&cin, &addrlen);if(-1 == new_fd){perror("accept error");return -1;}printf("[%s:%d]发来连接,new_fd = %d\n", inet_ntoa(cin.sin_addr),\ntohs(cin.sin_port) ,new_fd);//给当前新的套接字创建一个子进程用于跟客户端通信pid_t pid = fork();if(pid > 0){//关闭new_fdclose(new_fd);}else if(pid == 0){//关闭sfd文件描述符close(sfd);//5、使用新套接字跟客户端进行通信while(1){//从套接字中读取消息char rbuf[128] = "";          //存放接受消息的容器//int res = read(new_fd, rbuf, sizeof(rbuf)-1);int res = recv(new_fd, rbuf, sizeof(rbuf)-1, 0);if(res == 0){printf("客户端已下线\n");close(new_fd);exit(EXIT_SUCCESS);           //退出子进程}if(res == -1){perror("read error");close(new_fd);close(sfd);return -1;}//如果程序执行至此,表示数据成功读取下来,病放入rbuf中printf("[%s:%d] : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), rbuf);//给当前消息加个笑脸还回去strcat(rbuf, "*_*");//向套接字中写入消息//write(new_fd, rbuf, strlen(rbuf));send(new_fd, rbuf, strlen(rbuf), 0);printf("发送成功\n");}}//回收子进程资源}//6、关闭监听套接字close(sfd);return 0;
}

多线程客户端

#include<myhead.h>#define  SER_PORT  8888        //服务器端口号
#define SER_IP  "192.168.109.125"   //服务器IP地址 //定义一个结构体类型,用于主线程向分支线程传输多个数据
struct MsgInfo
{int new_fd;              //用于跟客户端通信的套接字文件描述符struct sockaddr_in cin;     //客户端套接字地址信息结构体
};//定义处理客户端消息的线程体函数
void *deal_cli_msg(void *arg)
{//将主线程传入的数据解析出来int new_fd = ((struct MsgInfo*)arg)->new_fd;struct sockaddr_in cin =  ((struct MsgInfo*)arg)->cin;//5、使用新套接字跟客户端进行通信while(1){//从套接字中读取消息char rbuf[128] = "";          //存放接受消息的容器//int res = read(new_fd, rbuf, sizeof(rbuf)-1);int res = recv(new_fd, rbuf, sizeof(rbuf)-1, 0);if(res == 0){printf("客户端已下线\n");close(new_fd);break;}if(res == -1){perror("read error");close(new_fd);return NULL;}//如果程序执行至此,表示数据成功读取下来,病放入rbuf中printf("[%s:%d] : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), rbuf);//给当前消息加个笑脸还回去strcat(rbuf, "*_*");//向套接字中写入消息//write(new_fd, rbuf, strlen(rbuf));send(new_fd, rbuf, strlen(rbuf), 0);printf("发送成功\n");}//退出线程pthread_exit(NULL);}/*****************************主线程********************/
int main(int argc, const char *argv[])
{//1、创建一个用于连接的套接字文件描述符int sfd  = socket(AF_INET, SOCK_STREAM, 0);if(-1 == sfd){perror("socket  error");return -1;}printf("socket 成功 sfd = %d\n", sfd);          //3//设置套接字属性:允许端口号快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、给套接字绑定ip地址和端口号//2.1 封装地址信息结构体变量struct sockaddr_in sin;        //地址信息结构体变量sin.sin_family = AF_INET;      //通信域地址族sin.sin_port = htons(SER_PORT);   //端口号网络字节序sin.sin_addr.s_addr = inet_addr(SER_IP);  //ip地址网络字节序//2.2  绑定操作if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) ==-1){perror("bind  error");return -1;}printf("bind success\n");//3、将套接字启动监听if(listen(sfd, 128) == -1){perror("listen  error");return -1;}printf("listen success\n");//4、阻塞等等客户端的连接,如果有新客户端连接,//则创建一个用于通信的套接字struct sockaddr_in cin;            //用于接受客户端套接字信息socklen_t addrlen = sizeof(cin);   //用于接受客户端套接字的长度while(1){//阻塞等等客户端的连接//对于accept函数而言,当执行到该函数时,即使没有客户端的连接//也会预选一个当前最小的文件描述符给新套接字//在阻塞过程中,即使有更小的,也不会选择,会留作下一次预选使用int new_fd = accept(sfd, (struct sockaddr*)&cin, &addrlen);if(-1 == new_fd){perror("accept error");return -1;}printf("[%s:%d]发来连接,new_fd = %d\n", inet_ntoa(cin.sin_addr),\ntohs(cin.sin_port) ,new_fd);//定义一个结构体变量,存储通信的套接字文件描述符和客户端地址信息结构体struct MsgInfo info = {new_fd, cin};//创建一个分之现场,用于跟客户端进行通信pthread_t tid = -1;if(pthread_create(&tid, NULL, deal_cli_msg, &info)!=0){printf("线程创建失败\n");return -1;}//将线程设置成分离态pthread_detach(tid);}//6、关闭监听套接字close(sfd);return 0;
}

http://www.dtcms.com/a/338494.html

相关文章:

  • Orbbec---setBoolProperty 快捷配置设备行为
  • docker回炉重造
  • PortainerCE 跨云管理:cpolar 内网穿透服务实现多环境统一控制
  • Lua学习记录 - 自定义模块管理器
  • Linux------《操作系统全景速览:Windows·macOS·Linux·Unix 对比及 Linux 发行版实战指南》
  • HiveQL | 个人学习笔记
  • JetBrains系列产品-IDEA/PyCharm/GoLand自动生成方法返回值的快捷键,查看方法参数的快捷键。
  • AI驱动的SEO关键词优化秘籍
  • MFC中使用EXCEL的方法之一
  • 数据迁移:如何从MySQL数据库高效迁移到Neo4j图形数据库
  • 迁移学习(Transfer Learning)
  • 当机器猫遇上具身智能:一款能读懂宠物心思的AI守护者
  • 分布式搜索(Elasticsearch)基本用法
  • kubeadm部署k8s集群环境搭建
  • Qt密码生成器项目开发教程 - 安全可靠的随机密码生成工具
  • QT聊天项目DAY19
  • 深入理解Prompt构建与工程技巧:API高效实践指南
  • 如何将Date类型的数据转换为LocalDateTime类型
  • 链表-2.两数相加-力扣(LeetCode)
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day7
  • Java开发面试实战:Spring Boot微服务与数据库优化案例分析
  • 微服务如何集成swagger3
  • Leetcode70爬楼梯
  • CF思维训练回顾
  • 摄像头模块在运动相机中的应用
  • 【Linux】文件系统
  • 【基础-判断】用户在长视频、短视频、直播、通话、会议、拍摄类应用等场景下,可以采用悬停适配在折叠屏半折态时,上屏进行浏览下屏进行交互操作
  • 工业相机基本知识解读:像元、帧率、数据接口等
  • ABAP - 会计凭证行项目文本和抬头文本增强
  • ios使用saveVideoToPhotosAlbum 保存视频失败提示 invalid video