【Linux网络编程】并发服务器之多线程模型
00. 目录
文章目录
- 00. 目录
- 01. 概述
- 02. 多线程服务器
- 03. 多线程服务器实现思路
- 04. 多线程服务器实现
- 05. 附录
01. 概述
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器。
循环服务器与并发服务器模型
在网络程序里面,一般来说都是许多客户对应一个服务器(多对一),为了处理客户的请求,对服务端的程序就提出了特殊的要求。
目前最常用的服务器模型
- 循环服务器:服务器在同一时刻只能响应一个客户端的请求。
- 并发服务器:服务器在同一时刻可以响应多个客户端的请求。
02. 多线程服务器
多线程服务器是对多进程的服务器的改进,由于多进程服务器在创建进程时要消耗较大的系统资源,所以用线程来取代进程,这样服务处理程序可以较快的创建。据统计,创建线程与创建进程要快 10100 倍,所以又把线程称为“轻量级”进程。线程与进程不同的是:一个进程内的所有线程共享相同的全局内存、全局变量等信息,这种机制又带来了同步问题。
03. 多线程服务器实现思路
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bwL4urkX-1595993960681)(assets/image-20200729113010149.png)]
04. 多线程服务器实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>/************************************************************************
函数名称: void *client_process(void *arg)
函数功能: 线程函数,处理客户信息
函数参数: 已连接套接字
函数返回: 无
************************************************************************/
void *client_process(void *arg)
{int recv_len = 0;char recv_buf[1024] = ""; // 接收缓冲区int connfd = (int)arg; // 传过来的已连接套接字// 接收数据while((recv_len = recv(connfd, recv_buf, sizeof(recv_buf), 0)) > 0){printf("recv_buf: %s\n", recv_buf); // 打印数据send(connfd, recv_buf, recv_len, 0); // 给客户端回数据}printf("client closed!\n");close(connfd); //关闭已连接套接字return NULL;
}//===============================================================
// 语法格式: void main(void)
// 实现功能: 主函数,建立一个TCP并发服务器
// 入口参数: 无
// 出口参数: 无
//===============================================================
int main(int argc, char *argv[])
{int sockfd = 0; // 套接字int connfd = 0;int err_log = 0;struct sockaddr_in my_addr; // 服务器地址结构体unsigned short port = 8080; // 监听端口pthread_t thread_id;printf("TCP Server Started at port %d!\n", port);sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字if(sockfd < 0){perror("socket error");exit(-1);}bzero(&my_addr, sizeof(my_addr)); // 初始化服务器地址my_addr.sin_family = AF_INET;my_addr.sin_port = htons(port);my_addr.sin_addr.s_addr = htonl(INADDR_ANY);printf("Binding server to port %d\n", port);// 绑定err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));if(err_log != 0){perror("bind");close(sockfd); exit(-1);}// 监听,套接字变被动err_log = listen(sockfd, 10);if( err_log != 0){perror("listen");close(sockfd); exit(-1);}printf("Waiting client...\n");while(1){char cli_ip[INET_ADDRSTRLEN] = ""; // 用于保存客户端IP地址struct sockaddr_in client_addr; // 用于保存客户端地址socklen_t cliaddr_len = sizeof(client_addr); // 必须初始化!!!//获得一个已经建立的连接 connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len); if(connfd < 0){perror("accept this time");continue;}// 打印客户端的 ip 和端口inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);printf("----------------------------------------------\n");printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));if(connfd > 0){//由于同一个进程内的所有线程共享内存和变量,因此在传递参数时需作特殊处理,值传递。pthread_create(&thread_id, NULL, (void *)client_process, (void *)connfd); //创建线程pthread_detach(thread_id); // 线程分离,结束时自动回收资源}}close(sockfd);return 0;
}
注意,上面例子给线程传参有很大的局限性,最简单的一种情况,如果我们需要给线程传多个参数,这时候我们需要结构体传参,这种值传递编译都通不过,这里之所以能够这么值传递,因为在32位系统中int 长度时 4 个字节, void * 长度也是 4 个字节。
05. 附录
【Linux】一步一步学Linux网络编程教程汇总
【Linux网络编程】并发服务器之多线程模型相关推荐
- Linux io模型及函数调用,Linux 网络编程的5种IO模型:信号驱动IO模型
Linux 网络编程的5种IO模型:信号驱动IO模型 背景 这一讲我们来看 信号驱动IO 模型. 介绍 情景引入: 在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个 ...
- 【Linux网络编程】并发服务器之select模型
00. 目录 文章目录 00. 目录 01. 概述 02. I/O复用技术概述 03. select模型服务器实现思路 04. select模型服务器实现 05. 附录 01. 概述 服务器设计技术有 ...
- 【Linux网络编程】并发服务器之多进程模型
00. 目录 文章目录 00. 目录 01. 概述 02. 多进程并发服务器 03. 多进程并发服务器实现思路 04. 多进程并发服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使用的 ...
- Linux 网络编程四(socket多线程升级版)
//网络编程--客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
- Linux 网络编程——并发服务器的三种实现模型
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器. 循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器(多 ...
- Linux网络编程 | 并发模式:半同步/半异步模式、领导者/追随者模式
文章目录 同步与异步 半同步/半异步模式 变体:半同步/半反应堆模式 改进:更高效的半同步/半异步模式 领导者/追随者模式 组件 :句柄集.线程集.事件处理器 并发模式是指I/O处理单元和多个逻辑单元 ...
- 【Linux】一步一步学Linux网络编程教程汇总(更新中......)
00. 目录 文章目录 00. 目录 01. 基础理论知识 02. 初级编程 03. 高级编程 04. LibEvent库 05. 06. 07. 01. 基础理论知识 [Linux网络编程]网络协议 ...
- 【Linux网络编程】循环服务器之TCP模型
00. 目录 文章目录 00. 目录 01. 概述 02. TCP循环服务器实现方法 03. TCP循环服务器模型 04. TCP循环服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使 ...
- 【Linux网络编程】循环服务器之UDP循环模型
00. 目录 文章目录 00. 目录 01. 概述 02. UDP循环服务器的实现方法 03. UDP循环服务器模型 04. UDP循环服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按 ...
最新文章
- 【pytorch】nn.conv1d的使用
- ae中心点重置工具_不懂这些知识,你的AE白学了!
- 非标准配置linux,剖析非标准波特率的设置和使用于Linux操作系统中
- golang经典书籍--Go语言圣经
- 【Linux】28.Linux脚本判断是否安装了某软件
- 【PAT乙级】1089 狼人杀-简单版 (20 分)
- 2021.02.01 Visual QA论文阅读
- 数据库异常关闭后无法启动问题处理
- 默认情况下安装的应用程序C盘后提示权限不足,当你开始介意。。。
- 360浏览器清凉新版让手机解暑
- (十五)final关键字
- Windows系统服务器IIS7.5 Asp.net支持10万请求的设置方法
- linux下怎么解压tar.gz,linux下怎么解压.tar.gz .tar.bz2命令
- ele表单验证的数字的坑
- 由边际成本引发的思考
- 2021-2027全球与中国地质与矿山规划软件市场现状及未来发展趋势
- 你玩的英雄在比赛中发挥如何呢?
- JavaFX - 制作登录窗口及界面跳转
- Essential singularity
- R语言第十讲 逻辑斯蒂回归
热门文章
- pytest入门学习(2)
- RESTORE DATABASE的standby选项
- 用javascript实现自动隐藏页面字段
- linux 同步 多终端,Linux系统如何实现不同终端间的同步
- 利用java格里高利公式求圆周率_用格里高利公式求π的近似值
- Java黑皮书课后题第8章:**8.11(游戏:九个硬币的正反面)一个3*3的矩阵中放置了9个硬币,这些硬币有些面朝上有朝下。1表示正面0表示反面,每个状态使用一个二进制数表示。使用十进制数表示状态
- 对C#面向对象三大特性的一点总结
- Eclipse配置关联Tomcat并运行项目
- JS实现全选、反选、不选
- win10被微软流氓更新后编译基于visual Studio的web项目报[ArgumentOutOfRangeException: 指定的参数已超出有效值的范围...