多线程高并发服务器:3个问题

2023-11-16

1.子线程能否关闭监听文件描述符?

2.主线程能否关闭通信文件描述符?

3.多个子线程共享cfd, 会有什么问题发生?

解答1:不能,父子线程共享文件描述符,若子进程关闭监听文件描述符之后,第二个子线程Accept时就会出错。Accept的第一个参数就是监听文件描述符。

解答2:不能,如果主线程关闭了通信文件描述符,直接会导致服务端读取失败,因为Read的第一个参数就是通信文件描述符。

解答3:如果多个客户端同时连接服务端 ,通信文件描述符会出现被覆盖的情况,只有最后一个文件描述符正常,导致只有一个客户端能正常通信。

解决办法:是这些子线程不在共享同一块内存,而改为共享一个数组(将内存分为合适大小的数组),这样就不会导致文件描述符被覆盖。

具体代码如下:

//多线程版本的服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
#include <pthread.h>
#include "wrap.h"

typedef struct info
{
	int cfd;   //若为-1表示可用, 大于0表示已被占用
	int idx;
	pthread_t thread;
	struct sockaddr_in client;
}INFO;

INFO thInfo[1024];

//线程执行函数
void *thread_work(void *arg)
{
	INFO *p = (INFO *)arg;
	printf("idx==[%d]\n", p->idx);

	char sIP[16];
	memset(sIP, 0x00, sizeof(sIP));
	printf("new client:[%s][%d]\n", inet_ntop(AF_INET, &(p->client.sin_addr.s_addr), sIP, sizeof(sIP)), ntohs(p->client.sin_port));

	int n;
	int cfd = p->cfd;
	struct sockaddr_in client;
	memcpy(&client, &(p->client), sizeof(client));
	
	char buf[1024];
	
	while(1)
	{
		memset(buf, 0x00, sizeof(buf));
		//读数据
		n = Read(cfd, buf, sizeof(buf));
		if(n<=0)
		{
			printf("read error or client closed, n==[%d]\n", n);
			Close(cfd);
			p->cfd =-1;  //设置为-1表示该位置可用
			pthread_exit(NULL);
		}
		
		for(int i=0; i<n; i++)
		{
			buf[i] = toupper(buf[i]);
		}
		//发送数据
		Write(cfd, buf, n);
	}
}

void init_thInfo()
{
	int i = 0;
	for(i=0; i<1024; i++)
	{
		thInfo[i].cfd = -1;;
	}
}

int findIndex()
{
	int i;
	for(i=0; i<1024; i++)
	{
		if(thInfo[i].cfd==-1)
		{
			break;
		}
	}
	if(i==1024)
	{
		return -1;
	}
	
	return i;
}

int main()
{
	//创建socket
	int lfd = Socket(AF_INET, SOCK_STREAM, 0);
	
	//设置端口复用
	int opt = 1;
	setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
	
	//绑定--将lfd 和 IP PORT绑定
	struct sockaddr_in serv;
	bzero(&serv, sizeof(serv));
	serv.sin_family = AF_INET;
	serv.sin_port = htons(8888);
	serv.sin_addr.s_addr = htonl(INADDR_ANY);
	Bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
	
	//监听
	Listen(lfd, 128);
		
	//初始化
	init_thInfo();
	
	int cfd;
	int ret;
	int idx;
	socklen_t len;
	pthread_t thread;
	struct sockaddr_in client;
	while(1)
	{
		len = sizeof(client);
		bzero(&client, sizeof(client));
		//获得一个新的连接
		cfd = Accept(lfd, (struct sockaddr *)&client, &len);
		//创建一个子进程, 让子进程处理连接---接收数据和发送数据
		
		//找数组中空闲的位置
		idx = findIndex();
		if(idx==-1)
		{
			Close(cfd);
			continue;
		}
		
		//对空闲位置的元素的成员赋值
		thInfo[idx].cfd = cfd;
		thInfo[idx].idx = idx;
		memcpy(&thInfo[idx].client, &client, sizeof(client));
		
		//创建子线程---该子线程完成对数据的收发
		ret = pthread_create(&thInfo[idx].thread, NULL, thread_work, &thInfo[idx]);
		if(ret!=0)
		{
			printf("create thread error:[%s]\n", strerror(ret));
			exit(-1);
		}
		
		//设置子线程为分离属性
		pthread_detach(thInfo[idx].thread);
	
	}
	
	Close(lfd);
	
	return 0;
	
}

接下来同时同三个客户端测试:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程高并发服务器:3个问题 的相关文章

随机推荐

  • layui后台表格的增删改查

    完整案例 github自己下下来 就是个很一般的ssm项目 但基本功能都有 已部署到云平台 后台管理员地址 暑假时候没做完凑合看吧 账号 17679210786 密码 123456 前后台都是 前台可以自己用手机号注册 别删除原来的内容 先
  • 攻防世界-MISC-练习区-12(功夫再高也怕菜刀)

    题目描述 菜狗决定用菜刀和菜鸡决一死战 这是攻防世界里面训练区的一道流量分析题 用wireshark 打开流量包 然后一级搜索http 二级用分组字节流搜索flag 按CTRL F 并找到no 1367 在Line based text d
  • 移动NB模块M5311(lwm2m协议登录详解)

    身为一个通信专业大三狗 第一次和别人对接项目今天属于我的功能总算是结束了 接下来就是等待联调 心情愉悦 首先NB是什么 这个我就不详细的解释了 我相信大多数人看这篇文章是以实践为开始的 那么多余的就不说了 接下来说具体流程 首先M5311模
  • 确实有必要好好学英语

    前言 工作已经6年多了 最近忽然明悟一些道理 零度觉得分享出来可能可以帮助一些人 这些道理可能很多成功的 牛逼的人早就知道这些了 随着技术的迭代更新越来越快 新技术不断产生 很多很多人都在焦虑 但是有一个道理的确是这样的 你不学习 未来终将
  • 【微信小程序】项目开发-----百度翻译API接口开发微信翻译小程序

    开发环境 微信开发者工具 V1 02 1902010版本以上 开发语言 JavaSript语言 HTML语言 API接口 百度翻译开发平台开放接口 界面预览 开发 基础配置 1 app js App onLaunch function 展示
  • AVPlay播放视频

    property nonatomic retain nullable AVPlayer player NSString urlStr NSBundle mainBundle pathForResource demo mp4 ofType n
  • 将灰度图片转成三通道(RGB)图片(MatLab)

    运行程序报错 RuntimeError output with shape 1 224 224 doesn t match the broadcast shape 3 224 224 报错原因 原模型输入的图片为RGB三通道 我输入的为单通
  • pytorch混合常量、变量

    有矩阵 X R n d X in R n times d
  • 蓝桥杯2015年第六届真题-赢球票

    题目 题目链接 题解 暴力 模拟 枚举每次从哪个位置开始 也就是有n种情况要枚举 对于每一种情况 我们都模拟这个过程 更新最大值 取牌操作结束的条件是还未被取走的数中的最大值都小于报的数了 说明没有办法取走任何一张了 此时结束 注意答案要求
  • docker安装rabbitmq

    1 准备 需要安装好docker环境 可以阅读文章在Centos和Redhat上安装Docker 小帅虎丶丿的博客 CSDN博客 学习如何安装docker 需要安装docker compose 了解yaml格式文件的编写以及一些常用的doc
  • 【python】如何使python中线程等待其他线程完了再执行;python-threading中的join方法;python的thread库如何判断子线程所绑定的函数全部执行完毕?

    1 主要方法 让所有的子线程都join 就可以了 不用join 的时候是这样的 用了join 之后是这样的 2 案例一 1 没有join import threading time def fun print 线程开始 print 我是线程
  • 国内几个主要的ubuntu 18.04 软件源

    1 阿里源 deb http mirrors aliyun com ubuntu bionic main restricted universe multiverse deb http mirrors aliyun com ubuntu b
  • R如何正确动态创建变量名,解决target of assignment expands to non-language object

    在一个群里 看到一位朋友发了一堆代码 错误代码 以及一个报错信息 Error in paste could not find function paste 还有一个target of assignment expands to non la
  • C++ 文档加密与解密运用【Crypto++】库

    一 下载Cryptopp 鼠标放到下面网址 点击下载即可 github地址 8 7 0版本 https github com weidai11 cryptopp releases tag CRYPTOPP 8 7 0 二 下载PEM包 pe
  • [1100]rocketmq详解

    文章目录 rocketmq入门 消息队列 rocketmq示例图 rocketmq应用场景 搭建环境 环境安装 Linux RocketMQ下载及安装 RocketMQ目录结构 RocketMQ启动及测试 管理工具 mqadmin管理工具
  • Navicat系列软件在win10中崩溃/闪退解决办法

    Navicat系列软件在win10中崩溃 在执行query gt run selected 的时候crash 安装了navicat 11的版本 经常在下拉菜单执行的过程中碰到闪退的情况 找过很多版本的安装包 都是如此 操作系统 win10
  • 程序员的关键思维

    在IT行业工作多年 越往后走 越是感觉到需要强调思考的能力 思考是我们底层非常关键的能力 尤其是在脑力密集 知识密集的行业里面显得更加重要 而这些思考的能力到底指的是什么 有没有什么方法论可以作为指导 让我们在日常的工作中不断精进 我最近试
  • [转]如何删除grub恢复windows操作系统的启动

    注 本文特别适合于在windows下已释放Linux所占空间 而启动时仍进入grub引导而不知如何解决的朋友 此文是我自己遇到这个问题时在网上搜到的 在此转载供大家参考 我自己采用的是方法四 确实比较简便 由于windows 2000 wi
  • 移植2- 移植uboot的spl代码

    根据http blog csdn net xiaojiaohuazi article details 8269890来修改 2014 3 2 做到第九步 这步还未做 疑问 uboot应该在BL2时才初始化内存吧 这里为什么这么早就初始化内存
  • 多线程高并发服务器:3个问题

    1 子线程能否关闭监听文件描述符 2 主线程能否关闭通信文件描述符 3 多个子线程共享cfd 会有什么问题发生 解答1 不能 父子线程共享文件描述符 若子进程关闭监听文件描述符之后 第二个子线程Accept时就会出错 Accept的第一个参