帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
服务器资讯 / 香港服务器租用 / 香港VPS租用 / 香港云服务器 / 美国服务器租用 / 台湾服务器租用 / 日本服务器租用 / 官方公告 / 帮助文档
多进程服务器和多线程服务器
发布时间:2024-03-07 16:48:10   分类:帮助文档
多进程服务器和多线程服务器 多进程服务器 #include #define PORT 9999 //端口号 #define IP "192.168.10.116" //IP地址 //定义信号处理函数,用于回收僵尸进程 void handler(int signo) { if(signo == SIGCHLD) { while(waitpid(-1, NULL, WNOHANG) > 0 ); } } //定义处理客户端操作的函数 int deal_cli_msg(int newfd, struct sockaddr_in cin) { //5、收发数据 char rbuf[128] = ""; //读取消息的容器 while(1) { //清空内容 bzero(rbuf, sizeof(rbuf)); int res = recv(newfd, rbuf, sizeof(rbuf), 0); if(res == 0) { printf("客户端下线\n"); break; } printf("[%s:%d] : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), rbuf); //链接一个字符串后发回去 strcat(rbuf, "*_*"); send(newfd, rbuf, sizeof(rbuf), 0); //功能:向newfd文件描述符中以阻塞形式写入数据 } close(newfd); return 0; } /主程序*/ int main(int argc, const char *argv[]) { //将SIGCHLD信号与信号处理函数进行绑定 if(signal(SIGCHLD, handler) == SIG_ERR) { perror("signal error"); return -1; } //1、创建套接字 int sfd = -1; //功能创建一个支持TCP通信的套接字 //AF_INET:表示跨主机的IPv4的通信 //SOCK_STREAM:表示支持TCP通信 if((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket error"); return -1; } printf("sfd = %d\n", sfd); //? //设置端口号快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1) { perror("setsockopt error"); return -1; } //2、绑定地址信息结构体(必须) //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; socklen_t socklen = sizeof(cin); //接收长度 //4.2 接收客户端链接请求 int newfd = -1; //用于跟客户端通信的套接字文件描述符 pid_t pid = -1; //接收子进程pid号 while(1) { //fork() 接收客户端链接请求 //当执行到accept时,系统会给该函数预分配一个文件描述符(按最小未使用原则) //所以,在该函数阻塞时,即使有旧的客户端退,释放了文件描述符,也不会再使用新释放的文件描述符 //下一次阻塞时,会预选上一次释放的文件描述符 if( (newfd=accept(sfd, (struct sockaddr*)&cin, &socklen)) == -1) { perror("accept error"); return -1; } printf("[%s:%d] 连接成功, newfd = %d\n", inet_ntoa(cin.sin_addr),\ ntohs(cin.sin_port), newfd); //? //创建子进程用于跟新的客户端进行通信工作 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; } //wait(NULL); //不能使用阻塞方式回收 } //关闭套接字 close(sfd); return 0; } 多线程服务器 #include #define PORT 9999 //端口号 #define IP "192.168.10.116" //IP地址 //定义向线程体中传递参数的结构体类型 struct pthread_ds { int newfd; //处理客户端的套接字文件描述符 struct sockaddr_in cin; //客户端套接字地址信息结构体变量 }; //定义线程处理函数 void *deal_cli_msg(void *arg) { //分解传过来的参数 int newfd = ((struct pthread_ds*)arg)->newfd; struct sockaddr_in cin = ((struct pthread_ds*)arg)->cin; //5、收发数据 char rbuf[128] = ""; //读取消息的容器 while(1) { //清空内容 bzero(rbuf, sizeof(rbuf)); int res = recv(newfd, rbuf, sizeof(rbuf), 0); if(res == 0) { printf("客户端下线\n"); break; } printf("[%s:%d] : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), rbuf); //链接一个字符串后发回去 strcat(rbuf, "*_*"); send(newfd, rbuf, sizeof(rbuf), 0); //功能:向newfd文件描述符中以阻塞形式写入数据 } close(newfd); //退出线程 pthread_exit(NULL); } /主程序*/ int main(int argc, const char *argv[]) { //1、创建套接字 int sfd = -1; //功能创建一个支持TCP通信的套接字 //AF_INET:表示跨主机的IPv4的通信 //SOCK_STREAM:表示支持TCP通信 if((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket error"); return -1; } printf("sfd = %d\n", sfd); //? //设置端口号快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1) { perror("setsockopt error"); return -1; } //2、绑定地址信息结构体(必须) //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; socklen_t socklen = sizeof(cin); //接收长度 //4.2 接收客户端链接请求 int newfd = -1; //用于跟客户端通信的套接字文件描述符 pthread_t tid = -1; //接收线程号 while(1) { //接收客户端链接请求 if( (newfd=accept(sfd, (struct sockaddr*)&cin, &socklen)) == -1) { perror("accept error"); return -1; } printf("[%s:%d] 连接成功, newfd = %d\n", inet_ntoa(cin.sin_addr),\ ntohs(cin.sin_port), newfd); //? //定义一个向线程体传递的结构体变量 struct pthread_ds info = {newfd, cin}; //创建一个分支线程,用于跟客户端进行通信 if(pthread_create(&tid, NULL, deal_cli_msg, &info) != 0) { printf("tid create error\n"); return -1; } //回收线程资源 //pthread_join(tid); //不能使用阻塞形式回收线程资源 pthread_detach(tid); //将线程设置成分离态 } //关闭套接字 close(sfd); return 0; }
香港云服务器租用推荐
服务器租用资讯
·广东云服务有限公司怎么样
·广东云服务器怎么样
·广东锐讯网络有限公司怎么样
·广东佛山的蜗牛怎么那么大
·广东单位电话主机号怎么填写
·管家婆 花生壳怎么用
·官网域名过期要怎么办
·官网邮箱一般怎么命名
·官网网站被篡改怎么办
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价