Linux十四(Tcp多线程及基于fork的多进程通信)

引入:当一个客户端与服务器建立连接以后,服务器端 accept()返回,进而准备循环接收客户端发过来的数据。如果客户端暂时没发数据,服务端会在 recv()阻塞。此时,其他客户端向服务器发起连接后,由于服务器阻塞了,无法执行 accept()接受连接,也就是其他客户端发送的数据,服务器无法读取。服务器也就无法并发同时处理多个客户端。
这个问题可以通过引入多线程和多进程来解决。服务端接受一个客户端的连接后,创建一个线程或者进程,然后在新创建的线程或进程中循环处理数据。主线程(父进程)只负责监听客户端的连接,并使用 accept()接受连接,不进行数据的处理。

多线程

示例代码:
在这里插入图片描述
执行结果示例:
在这里插入图片描述

不同的客户端在连接到服务器端时,会在创建的对应的线程里循环处理数据,即一个客户端对应一个线程,一个客户端不传数据时,不会影响其它的客户端通讯。

多进程

示例代码:
在这里插入图片描述
执行结果示例:
在这里插入图片描述

//添加了对子进程退出的异常信号处理
// 对父进程使用fork派生子进程后,如果子进程运行结束,那么该进程不会立刻被销毁,
// 而会进入“僵尸状态”,仍然维护着自身的信息,
// 这时候如果服务器父进程不加以处理,
// 那么很快就会消耗完系统的内存空间,所以父进程需要监听子进程SIGCHLD信号,
// 并做出处理以销毁残留信息,这里可以使用wait或者waitpid来实现。
// 我们在父进程调用listen之后,
// 注册监听信号和信号处理函数signal(SIGCHLD, SignalChild);
//
// SIGCHLD 进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。
// 缺省情况下该Signal会被忽略
signal(SIGCHLD, SignalChild); //子进程退出的信号处理

// FORK在子进程中返回0, 在父进程中返回子进程的ID
// 千万不要以为fork出来一个子进程就产生了2个新的socket描述符,
// 实际上子进程和父进程是共享socketFd和connect的,
// 每个文件和套接字都有一个引用计数,
// 引用计数在文件表项中维护,
// 它是当前打开着的引用该文件或套接字的描述符的个数。
// socket返回后与socketFd关联的文件表项的引用计数为1。
// accept返回后与connect关联的文件表项的引用计数也为1。
// 然后fork返回后,这两个描述符就在父进程与子进程间共享(也就是被复制),
// 因此与这两个套接字相关联的文件表项各自的访问计数值均为2。
// 这么一来,当父进程关闭connect时,
// 它只是把相应的引用计数值从2减为1。
// 该套接字真正的清理和资源释放要等到其引用计数值到达0时才发生。
// 这会在稍后子进程也关闭connect时发生。
//
// 因此当父进程关闭connect的时候它只是把这个connect的访问计数值减了1而已,
// 由于访问计数值还 > 0(因为还有客户端的connect连着呢),
// 所以它并没有断开和客户端的连接。
// 因此在fork之后socketFd和connect的引用计数均为2,父子进程均有一份
// 在父进程中, 需要关闭客户端连接套接字的文件描述符号connfd -= 1
// 在子进程中, 需要关闭服务器的文件socketFd,
// 因为他不需要监听客户端的连接 socketFd -= 1
// 然后处理完毕后需要关闭自己的客户端套接字connect -=
// 这样在客户端处理完信息后, connect== 0将被完全关闭
// socketFd仅在父亲进程中仍被打开

参考:https://www.csdn.net/
附:Tcp通信是半双工的(同一时刻一个信道只允许单方向传送,因此义被称为双向交替通信)

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值