目录

  • 多线程实现并发服务器
  • 多进程实现并发服务器

多线程实现并发服务器

server_thread.c

#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>//需要传入子线程的信息
struct sockInfo {int fd; // 通信的文件描述符struct sockaddr_in addr;pthread_t tid;  // 线程号
};struct sockInfo sockinfos[128];//同时支持128个线程void * working(void * arg) {// 子线程和客户端通信   cfd 客户端的信息 线程号// 获取客户端的信息struct sockInfo * pinfo = (struct sockInfo *)arg;//void * -> struct sockInfo *char cliIp[16];inet_ntop(AF_INET, &pinfo->addr.sin_addr.s_addr, cliIp, sizeof(cliIp));unsigned short cliPort = ntohs(pinfo->addr.sin_port);printf("client ip is : %s, prot is %d\n", cliIp, cliPort);// 接收客户端发来的数据char recvBuf[1024];while(1) {int len = read(pinfo->fd, &recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);}else if(len > 0) {printf("recv client : %s\n", recvBuf);} else if(len == 0) {printf("client closed....\n");break;}write(pinfo->fd, recvBuf, strlen(recvBuf) + 1);}close(pinfo->fd);return NULL;
}int main() {// 创建socketint lfd = socket(PF_INET, SOCK_STREAM, 0);if(lfd == -1){perror("socket");exit(-1);}struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;// 绑定int ret = bind(lfd,(struct sockaddr *)&saddr, sizeof(saddr));if(ret == -1) {perror("bind");exit(-1);}// 监听ret = listen(lfd, 128);if(ret == -1) {perror("listen");exit(-1);}// 初始化数据int max = sizeof(sockinfos) / sizeof(sockinfos[0]);//128for(int i = 0; i < max; i++) {bzero(&sockinfos[i], sizeof(sockinfos[i]));//初始化为0sockinfos[i].fd = -1;//-1代表文件描述符是可用的,没有被使用sockinfos[i].tid = -1;}// 循环等待客户端连接,一旦一个客户端连接进来,就创建一个子线程进行通信while(1) {struct sockaddr_in cliaddr;int len = sizeof(cliaddr);// 接受连接int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);struct sockInfo * pinfo;for(int i = 0; i < max; i++) {// 从这个数组中找到一个可以用的sockInfo元素if(sockinfos[i].fd == -1) {pinfo = &sockinfos[i];break;}if(i == max - 1) {sleep(1);i--;}}pinfo->fd = cfd;memcpy(&pinfo->addr, &cliaddr, len);//保存在堆内,这个函数结束后,不会被销毁,从而不影响子线程// 创建子线程pthread_create(&pinfo->tid, NULL, working, pinfo);pthread_detach(pinfo->tid);//pthread_join是阻塞的}close(lfd);return 0;
}

多进程实现并发服务器

server_process.c

#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>void recyleChild(int arg) {while(1) {int ret = waitpid(-1, NULL, WNOHANG);if(ret == -1) {// 所有的子进程都回收了break;}else if(ret == 0) {// 还有子进程活着break;} else if(ret > 0){// 被回收了printf("子进程 %d 被回收了\n", ret);}}
}int main() {struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = recyleChild;// 注册信号捕捉sigaction(SIGCHLD, &act, NULL);// 创建socketint lfd = socket(PF_INET, SOCK_STREAM, 0);if(lfd == -1){perror("socket");exit(-1);}struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;// 绑定int ret = bind(lfd,(struct sockaddr *)&saddr, sizeof(saddr));if(ret == -1) {perror("bind");exit(-1);}// 监听ret = listen(lfd, 128);if(ret == -1) {perror("listen");exit(-1);}// 不断循环等待客户端连接while(1) {struct sockaddr_in cliaddr;int len = sizeof(cliaddr);// 接受连接int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);if(cfd == -1) {if(errno == EINTR) {continue;}perror("accept");exit(-1);}// 每一个连接进来,创建一个子进程跟客户端通信pid_t pid = fork();if(pid == 0) {// 子进程// 获取客户端的信息char cliIp[16];inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, cliIp, sizeof(cliIp));unsigned short cliPort = ntohs(cliaddr.sin_port);printf("client ip is : %s, prot is %d\n", cliIp, cliPort);// 接收客户端发来的数据char recvBuf[1024];while(1) {int len = read(cfd, &recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);}else if(len > 0) {printf("recv client : %s\n", recvBuf);} else if(len == 0) {printf("client closed....\n");break;}write(cfd, recvBuf, strlen(recvBuf) + 1);}close(cfd);exit(0);    // 退出当前子进程}}close(lfd);return 0;
}

client.c

// TCP通信的客户端
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main() {// 1.创建套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd == -1) {perror("socket");exit(-1);}// 2.连接服务器端struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;inet_pton(AF_INET, "192.168.193.128", &serveraddr.sin_addr.s_addr);serveraddr.sin_port = htons(9999);int ret = connect(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));if(ret == -1) {perror("connect");exit(-1);}// 3. 通信char recvBuf[1024];int i = 0;while(1) {sprintf(recvBuf, "data : %d\n", i++);// 给服务器端发送数据write(fd, recvBuf, strlen(recvBuf)+1);int len = read(fd, recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);} else if(len > 0) {printf("recv server : %s\n", recvBuf);} else if(len == 0) {// 表示服务器端断开连接printf("server closed...");break;}sleep(1);}// 关闭连接close(fd);return 0;
}

第4章 Linux网络编程 22.多进程实现并发服务器、多线程实现并发服务器相关推荐

  1. Linux高性能服务器编程 第5章 Linux网络编程基础API

    5.1 socket 地址 API 现代CPU的累加器一次都能装载(至少)4 字节(这里考虑32位机,下同),即一个整 数.那么这4 字节在内存中排列的顺序将影响它被累加器装载成的整数的值.这就是字节 ...

  2. 【Linux网络编程部分----多进程高并发poll模型】

    目录 前言 背景 分析 编写步骤 服务器: 客户端: 服务器端代码 附:文件操作部分 附:目录操作部分 客户端代码 全部代码 头文件部分 服务器全部代码 客户端所有代码 总结: 前言 本文采用  Vi ...

  3. linux网络编程:使用多进程实现socket同时收发数据

    转载:http://blog.csdn.net/li_wen01/article/details/52685844 前面已讲过使用一个进程实现服务端和客户端P2P通信的实例,但是它只能同时处理一个客户 ...

  4. 第4章 Linux网络编程 24.端口复用

    目录 端口复用 查看网络相关信息的命令 端口复用 端口复用最常用的用途是: 防止服务器重启时之前绑定的端口还未释放 (2msl) 程序突然退出而系统没有释放端口 查看网络相关信息的命令 netstat ...

  5. 【Linux网络编程】并发服务器之多进程模型

    00. 目录 文章目录 00. 目录 01. 概述 02. 多进程并发服务器 03. 多进程并发服务器实现思路 04. 多进程并发服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使用的 ...

  6. Linux网络编程 五种I/O 模式及select、epoll方法的理解

    近期一次面试机会让我觉得有很多地方理解可能不到位,翻翻谷歌的资料加深对一些技术的理解 五种I/O 模式: [1] 阻塞 I/O (Linux下的I/O操作默认是阻塞I/O,即open和socket创建 ...

  7. Linux网络编程——黑马程序员笔记

    01P-复习-Linux网络编程 02P-信号量生产者复习 03P-协议 协议: 一组规则. 04P-7层模型和4层模型及代表协议 分层模型结构: OSI七层模型: 物.数.网.传.会.表.应TCP/ ...

  8. Linux网络编程基础

    2019独角兽企业重金招聘Python工程师标准>>> (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的 ...

  9. TCP/IP网络编程之多进程服务端(一)

    TCP/IP网络编程之多进程服务端(一) 进程概念及应用 我们知道,监听套接字会有一个等待队列,里面存放着不同客户端的连接请求,如果有一百个客户端,每个客户端的请求处理是0.5s,第一个客户端当然不会 ...

最新文章

  1. R语言笔记1:数据类型(向量、数组、矩阵、 列表和数据框)
  2. 如何实现高容量大并发数据库服务 | 数据库分布式架构设计
  3. python sys模块讲解_python模块之sys模块和序列化模块(实例讲解)
  4. boost::make_ready_future相关的测试程序
  5. node 命令行升级版本
  6. 谷沉沉:专注视频技术十几年
  7. Android开发之Dialog对话框(弹框)工具类
  8. WPF 基础控件之CheckBox样式
  9. 为什么你应该使用OpenGL而不是DirectX?
  10. [js] 微信的JSSDK都有哪些内容?如何接入?
  11. 简单的动态JavaScript Ajax函数
  12. WinForm两点注意的地方
  13. 用Java+Html+MySQL 实现注册、登录(servlet框架)-(一)
  14. java第二季_Java入门第二季
  15. Android游戏开发中使用Libgdx引擎遇到的问题及解决办法汇总
  16. 1.命令行窗口(小黑屏)、CMD窗口、终端、shell、DOS窗口
  17. 超级干货 :一文读懂社交网络分析(附应用、前沿、学习资源)
  18. android抓trace工具,Android性能优化工具之TraceView
  19. ADMM algorithm
  20. 2009年ACM-ICPC——瑞典取双

热门文章

  1. 2021年全球结构螺栓收入大约796.4百万美元,预计2028年达到1097.6百万美元
  2. go语言之面向对象编程
  3. 【180930】坦克大战小游戏源码
  4. 体育品牌争夺体育明星前必读的12条法则
  5. vant van-uploader 微信内置浏览器 打开h5页面 无法调起手机拍照
  6. Windows对Ubuntu的远程控制,你会几种方法?
  7. python 中类的初始化方法
  8. Unity--Vector3的使用
  9. ApachePOI操作Excel快速入门使用
  10. xlsx.full.js读取Excel数据转换成二维数组,sheet_to_array