技术资讯

并发服务器三种实现方式之进程、线程和select

TIME:2018-09-19

前言:刚开始学网络编程,都会先写一个客户端和服务端,不知道你们有没有试一下:再打开一下客户端,是连不上服务端的。还有一个问题不知道你们发现没:有时启服务器,会提示“Address already in use”,过一会就好了,想过为啥么?在这篇博客会解释这个问题。

但现实的服务器都会连很多客户端的,像阿里服务器等,所以这篇主要介绍如何实现并发服务器,主要通过三种方式:进程、线程和select函数来分别实现。

一、进程实现并发服务器

先说下什么是并发服务器吧?不是指有多个服务器同时运行,而是可以同时连接多个客户端。

先简单说下原理吧,先画个图,如下:  PS:全博客园最丑图,不接受反驳!哈哈哈

先要搞清楚通信的流程,图上参数说明:

lfd:socket函数的返回值,就是监听描述符

cfd1/cfd2/cfd3:accept函数的返回值,用通信的套接字

server:服务器

client:客户端

socket通信过程中,总共有几个套接字呢?答:三个,客户端一个,服务器两个。

根据上图来大致说明一下流程:

客户端创建一个套接字描述符,用于通信,服务器先用socket函数创建套接字,用于监听客户端,然后调用accept函数,会返回一个套接字,用于通信的。图上就是,client1先通过cfd与server建立连接,然后与cfd1建立连接通信,这时lfd就空闲了,再监听客户端,client2再与lfd连接,再跟cfd2通信。client3也是如此。

现在问题就是。如何创建多个进程与客户端通信呢?通过循环创建子进程就可以实现这个问题,可以参考我的这篇博客:https://www.cnblogs.com/liudw-0215/p/9667686.html

服务端程序,如下:


View Code

客户端程序如下:


View Code

演示效果,服务器可以同时处理两个客户端,如下:

但我想再测试一下程序,执行./server,发现有个bind error,如下:

下面来解释一下这个问题:

先来一张图片(出自UNP),如下:

这张图将三次握手、四次挥手和TCP状态转换图,这些在我的这篇博客都由介绍,可以参考一下:https://www.cnblogs.com/liudw-0215/p/9661583.html

注意最后有一个TIME_WAIT状态,主动关闭一端会经历2MSL时长等待(大约40秒),再变为最开始的状态CLOSED。

复现上面的“bind error”,只需退出服务器,在启服务器,就会报出此错。因为主动关闭一端,会经历2MSL时长,端口IP会被占用,所以会报“bind error”。

但可能会问:为啥先退出客户端没有此问题?因为客户端没有调用bind函数地址结构,会“隐式”生成端口。

有没有方法可以解决这个问题呢?当然有的,调用函数setsockopt即可,服务端程序如下:


View Code

二、线程实现并发服务器

理解了进程的方式,就是创建多个线程来实现,就不过多解释了,程序需要对线程有一定了解,之后我还会写篇博客来介绍线程,敬请期待哦。

服务器代码如下,有有详细的解释:


View Code

客户端代码如下:


View Code

三、select实现并发服务器

select和进程主要区别在于,进程是阻塞的,而select是交给内核自己来实现的,由于select比较复杂,参考我的另一篇文章:
http://www.qhdsq.net/index.php/home/index/jszc_nr/id/1071

上一篇

电商软件开发:select实现高并发服务器

下一篇

网站开发:mysql高并发请求 + 事务嵌套 + 更新数据 = 死锁