多线程实践(一)——# 基于多线程实现的并发服务器

基于多线程实现的并发服务器

//server
#include <iostream>
#include <cstring>
#include <thread>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;struct SockInfo {int fd;      // 通信句柄pthread_t pid; // 线程idsockaddr_in addr; // 客户端地址
};SockInfo sock_infos[128];
sockaddr_in server_addr;int listenfd;bool InitServer(unsigned int port, unsigned int backlog) {  // backlog为单个线程的最大连接数listenfd = socket(AF_INET, SOCK_STREAM, 0);  // 初始化服务端的监听if (listenfd < 0) {perror("listensocket init failed");return false;}memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡int ret = bind(listenfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); // 绑定if (ret < 0) {perror("bind failed");return false;}ret = listen(listenfd, backlog);if (ret < 0) {perror("listen failed");return false;}return true;
}void* worker(void* arg) {SockInfo* pinfo = (SockInfo*)arg;cout<<"child thread, connfd: " << pinfo->fd << endl;while (true) {char buff[1024];memset(buff, 0, sizeof(buff));int ret = recv(pinfo->fd, buff, sizeof(buff), 0);if (ret == 0) {cout << "client disconnected" << endl;pinfo->fd = -1;break;} else if (ret == -1) {perror("recv failed");break;}cout << "receive msg: " << buff << endl;ret=send(pinfo->fd,buff,strlen(buff),0); if(ret==-1){perror("send failed");return 0;}cout<<"send msg: "<<buff<<endl;}close(pinfo->fd);pthread_exit(NULL);
}int main(int argc, char* argv[]) {if (argc < 2) {cerr << "Usage: " << argv[0] << " <port>" << endl;return EXIT_FAILURE;}unsigned int port = atoi(argv[1]);if (!InitServer(port, 5)) {exit(EXIT_FAILURE);}int max = sizeof(sock_infos) / sizeof(sock_infos[0]);for (int i = 0; i < max; i++) {memset(&sock_infos[i], 0, sizeof(sock_infos[i]));sock_infos[i].fd = -1;sock_infos[i].pid = -1;}SockInfo* pinfo;while (true) {// 创建子线程int found = 0;for (int i = 0; i < max; i++) {if (sock_infos[i].fd == -1) {pinfo = &sock_infos[i];found = 1;break;}}if (!found) {  // 如果没有找到空闲位置// 拒绝新的连接请求int connfd = accept(listenfd, (struct sockaddr*)&pinfo->addr, (socklen_t*)&(pinfo->addr));if (connfd != -1) {char error_msg[] = "已达到连接数的最大值\n";send(connfd, error_msg, sizeof(error_msg) - 1, 0);  // 发送错误信息close(connfd);  // 关闭连接continue;}}int connfd = accept(listenfd, (struct sockaddr*)&pinfo->addr, (socklen_t*)&(pinfo->addr));if (connfd == -1) {perror("accept failed");continue;}pinfo->fd = connfd;cout << "parent thread, connfd: " << connfd << endl;// 创建线程处理客户端连接pthread_create(&pinfo->pid, NULL, worker, pinfo);pthread_detach(pinfo->pid);  // 设置线程为分离状态}close(listenfd);return 0;
}
// client
#include <iostream>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>using namespace std;int main(int argc,char *argv[])
{if(argc!=3){cout<<"Examples: ./demo1 服务端 端口号"<<endl;return -1;}//创建socket套接字int socketid=socket(AF_INET,SOCK_STREAM,0);if(socketid==-1){perror("socket error");return -1;}//绑定服务端struct hostent* h;  //存放服务端IP的数据结构if((h=gethostbyname(argv[1]))==0){perror("gethostbyname error");close(socketid);return -1;}struct sockaddr_in serveraddr;memset(&serveraddr,0,sizeof(serveraddr));serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(atoi(argv[2]));if(connect(socketid,(struct sockaddr*)&serveraddr,sizeof(serveraddr))==-1){perror("connect error");close(socketid);return -1;}//通讯int iret;char buffer[1024];memset(buffer,0,sizeof(buffer));for(int i=1;i<10;i++){//发送报文sprintf(buffer,"这是第%d份报文",i);if((iret=send(socketid,buffer,strlen(buffer),0))==-1){perror("send error");close(socketid);break;}sleep(10);cout<<"发送成功"<<endl;//接收回应报文memset(buffer,0,sizeof(buffer));if((iret=recv(socketid,buffer,sizeof(buffer),0))==-1){perror("recv error");close(socketid);break;}cout<<"接收成功"<<endl;}//断开连接,释放资源close(socketid);cout<<"连接已断开"<<endl;return 0;
}
```

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1557184.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C语言基础题(大合集1)

1. Hello World! 写一个程序 &#xff0c; 在控制台上输出 &#xff1a; Hello World! #include <stdio.h> int main() {printf("Hello World!\n");return 0; }main 函数是程序的入口 &#xff0c; 一个工程有且仅有一个 main函数 代码是从 main 函数的第一行开…

数学概念算法-打印100以内的素/质数

素数&#xff1a;只能被1和自己整除的数 暴力破解 埃氏筛选 找到第一个数字&#xff0c;如果它是素数&#xff0c;则把它的倍数全部划掉 比如数字2是素数&#xff0c;那么 4,6,8,10,12。这些数字肯定不是素数&#xff0c;所以不用再考虑&#xff0c;直接划掉即可 第二步&#…

SQL注入靶场sqli-labs less-4

sqli-labs靶场第三关less-4 1、确定注入点 http://192.168.128.3/sq/Less-4/?id1 http://192.168.128.3/sq/Less-4/?id2 有不同回显&#xff0c;判断可能存在注入&#xff0c; 2、判断注入类型 输入 http://192.168.128.3/sq/less-4/?id1 and 11 http://192.168.128.3/sq/l…

C++(异常)

目录 C语言传统的处理错误的方式 传统的错误处理机制 C异常概念 异常的使用 异常的抛出和捕获 异常的抛出和匹配原则 在函数调用链中异常栈展开匹配原则 异常的重新抛出 异常安全 异常规范 自定义异常体系 C标准库的异常体系 异常的优缺点 C异常的优点 C异常的缺…

DB_GPT excel研究

DB_GPT excel研究 摘要视频简介源码分析excel文档上传预处理对话 摘要 DB_GPT集成了很多对话方式&#xff0c;其中呢就有关于excel对话的模块&#xff0c;我搜集各大web好像都没有关于这个模块的研究&#xff0c;于是乎就自行研究了对于excel对话的的功能 如果是想看与数据库…

Golang | Leetcode Golang题解之第462题最小操作次数使数组元素相等II

题目&#xff1a; 题解&#xff1a; func partition(a []int, l, r int) int {x : a[r]i : l - 1for j : l; j < r; j {if a[j] < x {ia[i], a[j] a[j], a[i]}}a[i1], a[r] a[r], a[i1]return i 1 }func randomPartition(a []int, l, r int) int {i : rand.Intn(r-l1…

毕设 大数据电影数据分析与可视化系统(源码+论文)

文章目录 0 前言1 项目运行效果2 设计概要3 最后 0 前言 &#x1f525;这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师…

51 单片机最小系统

一、51 单片机最小系统概述 51 单片机最小系统是一个基于 51 单片机的最小化电路系统&#xff0c;它包含了使单片机能够正常工作的最少元件。这个系统主要用于学习和实验目的&#xff0c;帮助学习者在没有复杂电路的情况下快速了解 51 单片机的工作原理&#xff0c;其重要性不…

动态规划算法专题(四):子串、子数组系列

目录 1、最大子数组和 1.1 算法原理 1.2 算法代码 2、环形子数组的最大和 2.1 算法原理 2.2 算法代码 3、乘积最大子数组 3.1 算法原理 3.2 算法代码 4、乘积为正数的最长子数组长度 4.1 算法原理 4.2 算法代码 5、等差数列划分 5.1 算法原理 5.2 算法代码 6、…

java语言基础案例-cnblog

java语言基础案例 象棋口诀 输出 package nb;public class XiangQi {public static void main(String[] args) {char a 马;char b 象;char c 卒;System.out.println(a"走日"b"走田""小"c"一去不复还");} }输出汇款单 package nb…

30 树 · 二叉树

目录 一、树 &#xff08;一&#xff09;树的概念与结构 &#xff08;二&#xff09;树相关术语 &#xff08;三&#xff09;树的表示 &#xff08;四&#xff09;树形结构的实际应用场景 二、二叉树 &#xff08;一&#xff09;概念与结构 &#xff08;二&#xff09;…

【LeetCode】每日一题 2024_10_7 最低加油次数(堆、贪心)

前言 每天和你一起刷 LeetCode 每日一题~ 大家国庆节快乐呀~ LeetCode 启动&#xff01; 国庆最后一天&#xff0c;力扣还在加油站&#xff0c;怕不是国庆回家路上堵车了 题目&#xff1a;最低加油次数 代码与解题思路 func minRefuelStops(target int, startFuel int, st…

刷题 双指针 滑动窗口

面试经典 150 题 - 双指针 ⭐️125. 验证回文串 学会内部字母处理函数的使用 class Solution { public:bool isPalindrome(string s) {int left 0, right s.size() - 1;while (left < right) {// 处理左边字符if (!isalnum(s[left])) {left;continue;}// 处理右边字符if…

C(十五)函数综合(一)--- 开公司吗?

在这篇文章中&#xff0c;杰哥将带大家 “开公司”。 主干内容部分&#xff08;你将收获&#xff09;&#xff1a;&#x1f449; 为什么要有函数&#xff1f;函数有哪些&#xff1f;怎么自定义函数以及获得函数的使用权&#xff1f;怎么对函数进行传参&#xff1f;函数中变量的…

C语言 | Leetcode C语言题解之第462题最小操作次数使数组元素相等II

题目&#xff1a; 题解&#xff1a; static inline void swap(int *a, int *b) {int c *a;*a *b;*b c; }static inline int partition(int *nums, int left, int right) {int x nums[right], i left - 1;for (int j left; j < right; j) {if (nums[j] < x) {swap(…

Linux 外设驱动 应用 1 IO口输出

从这里开始外设驱动介绍&#xff0c;这里使用的IMX8的芯片作为驱动介绍 开发流程&#xff1a; 修改设备树&#xff0c;配置 GPIO1_IO07 为 GPIO 输出。使用 sysfs 接口或编写驱动程序控制 GPIO 引脚。编译并测试。 这里假设设备树&#xff0c;已经配置好了。不在论述这个问题…

【英语】5. 考研英语语法体系

文章目录 前言句字的成分一、常规句型简单句&#xff08;5 种&#xff09;1. 定义&#xff1a;句子中只包含 *一套主谓结构* 的句子。&#xff08;一个句子只能有一个谓语动词&#xff09;2. 分类 并列句&#xff08;由关联词组成&#xff09;&#xff08;3 种&#xff09;基本…

二分图算法总结 C++实现

总体概念 染色法 基本思路步骤 将所有的边及其相接的边用邻接表存储起来&#xff1b;遍历所有的点&#xff0c;找到未上色的点&#xff1b;用BFS将该点及其相接的点迭代上色&#xff1b;在上述染色步骤中&#xff0c;如果相邻点的颜色相同则无法形成二分图&#xff1b; 题目…

继电保护之电压重动、电压并列和电压切换

实践&#xff1a;以某开关室10kV母联隔离柜为例&#xff1a; ZYQ-824为PT并列装置&#xff0c;装置内包含一系列继电器&#xff0c;用于PT重动及并列。按照装置编号原则&#xff0c;交流电压切换箱一般命名为7n。 ​下图为装置内继电器线圈部分接线&#xff1a; 下图为装置内…

销售秘籍:故事+观点+结论

在销售的浩瀚宇宙中&#xff0c;隐藏着一个不朽的秘诀——利用人类共有的“错失恐惧”&#xff0c;激发客户内心的渴望与行动。正如村上春树所言&#xff0c;每个故事都深深植根于灵魂&#xff0c;而大仲马则揭示&#xff0c;灵魂之眼所见&#xff0c;比肉眼更为长久铭记。 错…