C/S架构聊天室项目预备问题及处理方案


在熟悉了TCP编程模型后,可以发现其中的一些问题,如何让一个服务端程序服务众多客户端是我们要解决的第一个问题。在服务器编程中有很多解决的方法,比如多线程、多进程、复用IO等等,在这里讨论利用多线程和select复用IO的方式简单解决服务端程序服务多个客户端的问题,并实现C/S架构的聊天室简单程序。

一般TCP客户端、服务端编程模型

首先理解阻塞的概念。服务端某些函数(例如accept,read/recv,write/send等)都可能阻塞服务端程序,直到该函数调用完成,或阻塞超时后才会继续向下执行。
传统的服务端程序解决办法,不外乎于顺序执行程序,利用循环阻塞等方法达到连续接收客户端请求的目的。可以见下图。

在这里插入图片描述
第一个问题是 服务端同时处理多个客户端请求时,需要处理的情况有很多种,比如新客户端等待与服务端建立连接,已连接客户端发送数据,已连接客户端断开连接等等情况,如果服务器采用轮询阻塞的方式运行,那么同一时刻只能处理一种情况,这时其他情况发生就要等待阻塞结束。最坏的情况是一直阻塞,服务器也一直不能处理其他情况。
第二个问题是 服务端在使用read/recv函数阻塞等待接收客户端发来的消息时,同一时刻只能处理一个客户端,此时如果其他客户端发来消息,服务端仍处于阻塞等待状态,无法切服务换到其他客户端。
根据问题,Linux系统中也有相应的的解决办法。解决功能阻塞可以使用多线程编程,解决多客户端阻塞可以使用复用IO,这里以select为例。

多线程编程

在Linux系统中多线程是一种开销比较小的实现并发执行的方法。我们可以开启新线程,将比较耗时的工作(阻塞就非常耗时)放到新线程中执行,主线程则不会受到影响而继续向下执行。

打个比方在做饭时需要烧火和挑水,如果只有一个人他只能挑一次水烧一会儿火,这时假如有个人过来帮他烧火,那么他就可以专心挑水,把饭做熟的时间相应就要缩短,而且他不用担心火灭掉或者水不够。

在服务端acceptread都会阻塞程序,所以将他们放在两个线程里,每个线程只负责阻塞等待一件事,这样不同的情况发生时就会有不同的线程应对,达到并行处理的目的。

这里我们将accept放在主线程中,read函数放在创建的新线程中。当主线程执行完初始化网络的工作后,执行accept阻塞等待新连接进入,线程B阻塞等待已经连接的客户端发送消息。

通过锁,线程间通信,线程间同步等手段,实现两个线程可以分别处理自己的工作。服务端处理事务的示意图如下
在这里插入图片描述
Linux遵循pthread(POSIX threads)方式创建线程,主要的操作函数和同步函数有下面几种。

函数 作用
pthread_create() 创建一个线程
pthread_exit() 终止当前线程
pthread_cancel() 中断另外一个线程的运行
pthread_join() 阻塞当前的线程,直到另外一个线程运行结束

在使用线程时,要注意线程安全的问题。不同的线程同时操作同一个变量是有危险的,如果一个线程正在写,另一个线程发生读事件,那么读到的内容究竟是什么将不确定。所以多线程使用全局变量时注意加锁处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值