基于Linux socket聊天室-多线程服务器问题处理(02)

简介: 基于Linux socket聊天室-多线程服务器问题处理(02)

     根据上篇文章中,遗留的问题,进行进一步的分析。

     server创建子线程的时候用的是以下代码:

pconnsocke = (int *) malloc(sizeof(int));
  *pconnsocke = new_fd;
  ret = pthread_create(&tid, NULL, rec_func, (void *) pconnsocke);
  if (ret < 0) 
  {
   perror("pthread_create err");
   return -1;
  }

   为什么必须要malloc一块内存专门存放这个新的套接字呢?

要讲清楚这个问题的原因需要一些背景知识:

  1. Linux创建一个新进程时,新进程会创建一个主线程;
  2. 每个用户进程有自己的地址空间,系统为每个用户进程创建一个task_struct来描述该进程, 实际上task_struct 和地址空间映射表一起用来,表示一个进程;
  3. Linux里同样用task_struct来描述一个线程,线程和进程都参与统一的调度;
  4. 进程内的不同线程执行是同一程序的不同部分,各个线程并行执行,受操作系统异步调度;
  5. 由于进程的地址空间是私有的,因此在进程间上下文切换时,系统开销比较大;
  6. 在同一个进程中创建的线程共享该进程的地址空间。

明白这些基础知识后,下面我来看下,当进程创建一个子线程的时候,传递的参数情况:

直接传递栈中内存地址

我们首先分析下如果创建子线程传递的是局部变量new_fd的地址这种情况。

由上图所示:

  1. 创建一个线程,如果我们按照图中传递参数方法,那么new_fd是在栈中的,创建子线程的时候我们把new_fd地址传递给了thread1,线程回调参数arg的地址是new_fd地址。
  2. 因为主函数会一直循环不退出,所以new_fd一直存在栈中。用这种方法的确可以把new_fd的值3传递到子线程的局部变量fd,这样子线程就可以使用这个fd与客户端通信。
  3. 但是因为我们设计的是并发服务器模型,我们没有办法预测客户端什么时候会连接我们的服务器,假设遇到一个极端情况,在同一时刻,多个客户端同时连接服务器,那么主线程是要同时创建多个子线程的。

多个客户端同时连接服务器

如上图所示,所有新建的的thread回调函数的参数arg存放的都是new_fd的地址。如果客户端连接的时候时间间隔比较大,是没有问题的,但是在一些极端的情况下还是有可能出现由于高并发引起的错误。

我们来捋一下极端的调用时序:

第一步:

如上图所示:

  1. T1时刻,当客户端1连接服务器的时候,服务器的accept函数会创建新的套接字4;
  2. T2时刻,创建了子线程thread1,同时子线程回调函数参数arg指向了栈中new_fd对应的内存。
  3. 假设,正在此时,又有一个客户端要连接服务器,而且thread1页已经用尽了时间片,那么主线程server会被调度到。

第二步:

如上图所示:

  1. T3时刻,主线程server接受了客户端的连接,accept函数会创建新的套接字5,同时创建子线程thread2,此时OS调度的thread2;
  2. T4时刻,thread2通过arg得到new_fd了的值5,并存入fd;
  3. T5时刻,时间片到了,调度thread1,thread1通过arg去读取new_fd,此时栈中new_fd的值已经修5覆盖了;
  4. 所以出现了2个线程同时使用同一个fd的情况发生。

这种情况的发生,虽然概率很低,但是并不代表不发生,该bug就是一口君在解决实际项目中遇到过的。

传递堆内存地址

如果采用传递堆的地址的方式,我们看下图:

  1. T1时刻,当客户端1连接服务器的时候,服务器的accept函数会创建新的套接字4,在堆中申请一块内存,用指针pconnsocke指向该内存,同时将4保存到堆中;
  2. T2时刻,创建了子线程thread1,同时子线程回调函数参数arg指向了堆中pconnsocke指向的内存。
  3. 假设,正在此时,又有一个客户端要连接服务器,而且thread1页已经用尽了时间片,那么主线程server会被调度到。
  4. T3时刻,主线程server接受了客户端的连接,accept函数会创建新的套接字5,在堆中申请一块内存,用指针pconnsocke指向该内存,同时将5保存到堆中,然后创建子线程thread2;
  5. T4时刻,thread2通过arg指向了堆中pconnsocke指向的内存,此处值为5,并存入fd;
  6. T5时刻,时间片到了,调度thread1,thread1通过arg去读取fd,此时堆中数据位5;
  7. 就不会出现了2个线程同时使用同一个fd的情况发生。

这个知识点有点隐蔽,希望读者在使用的时候多加小心。

目录
相关文章
|
2月前
|
安全 Java Linux
Websoft9:为开发者打造的高效 Linux 服务器面板
Websoft9 是一款以开源应用部署与管理为核心的服务器面板,采用“环境即服务”模式。它通过运行环境标准化、自动化配置、安全融合和资源管理四个方面实现平台与环境的深度协同。支持多语言框架预集成、云原生组件整合,提供 200+ 应用模板一键部署,并具备全流程安全防护和统一资源监控能力,助力开发者高效管理和扩展应用环境。
72 0
|
1月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
149 67
|
28天前
|
安全 Linux
阿里云linux服务器使用脚本通过安全组屏蔽异常海外访问ip
公网网站可能会遭受黑客攻击导致访问异常,使用此脚本可以屏蔽掉异常IP 恢复访问。也可自行设置定时任务定期检测屏蔽。
146 28
|
1月前
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
109 28
|
1月前
|
JavaScript Linux Python
在Linux服务器中遇到的立即重启后的绑定错误:地址已被使用问题解决
总的来说,解决"地址已被使用"的问题需要理解Linux的网络资源管理机制,选择合适的套接字选项,以及合适的时间点进行服务重启。以上就是对“立即重启后的绑定错误:地址已被使用问题”的全面解答。希望可以帮你解决问题。
104 20
|
2月前
|
Ubuntu Linux
Linux系统管理:服务器时间与网络时间同步技巧。
以上就是在Linux服务器上设置时间同步的方式。然而,要正确运用这些知识,需要理解其背后的工作原理:服务器根据网络中的其他机器的时间进行校对,逐步地精确自己的系统时间,就像一只犹豫不决的啮齿动物,通过观察其他啮齿动物的行为,逐渐确定自己的行为逻辑,既简单,又有趣。最后希望这个过程既能给你带来乐趣,也能提高你作为系统管理员的专业素养。
132 20
|
2月前
|
网络协议 开发者 Python
Socket如何实现客户端和服务器间的通信
通过上述示例,展示了如何使用Python的Socket模块实现基本的客户端和服务器间的通信。Socket提供了一种简单且强大的方式来建立和管理网络连接,适用于各种网络编程应用。理解和掌握Socket编程,可以帮助开发者构建高效、稳定的网络应用程序。
105 10
|
2月前
|
存储 运维 监控
深度体验阿里云系统控制台:SysOM 让 Linux 服务器监控变得如此简单
作为一名经历过无数个凌晨三点被服务器报警电话惊醒的运维工程师,我对监控工具有着近乎苛刻的要求。记得去年那次大型活动,我们的主站流量暴增,服务器内存莫名其妙地飙升到90%以上,却找不到原因。如果当时有一款像阿里云 SysOM 这样直观的监控工具,也许我就不用熬通宵排查问题了。今天,我想分享一下我使用 SysOM 的亲身体验,特别是它那令人印象深刻的内存诊断功能。
|
21天前
|
存储 缓存 弹性计算
阿里云经济型e实例云服务器评测:企业官网搭建的性价比之选
阿里云服务器经济型e实例可以用来搭建企业网站吗?云服务器作为搭建企业官网的基础设施,其性能、稳定性、成本等因素直接影响着官网的运营效果。阿里云经济型e实例云服务器作为一款性价比较高的产品,备受用户关注。许多企业在选择云服务器搭建官网时,都会将其纳入考虑范围。本文将详细探讨阿里云经济型e实例云服务器的特点、性能表现、稳定性与可靠性,以及成本考量,最终解答是否适合用它来搭建企业官网。
|
2月前
|
存储 缓存 网络协议
阿里云特惠云服务器99元与199元配置与性能和适用场景解析:高性价比之选
2025年,阿里云长效特惠活动继续推出两款极具吸引力的特惠云服务器套餐:99元1年的经济型e实例2核2G云服务器和199元1年的通用算力型u1实例2核4G云服务器。这两款云服务器不仅价格亲民,而且性能稳定可靠,为入门级用户和普通企业级用户提供了理想的选择。本文将对这两款云服务器进行深度剖析,包括配置介绍、实例规格、使用场景、性能表现以及购买策略等方面,帮助用户更好地了解这两款云服务器,以供参考和选择。