服务端并发处理多个客户端的请求
多线程处理
多进程处理,可升级为进程池
IO多路转接,可以在单线程的情况下处理多个请求,可搭配多线程处理
libevent,一个开源框架
客户端要进行数据上传和下载,就需要和服务器建立多个连接,可以在客户端创建套接字连接池,每个连接对应一个业务流程、
编程流程
对于服务端
- 创建流式套接字
- 绑定地址信息
- 监听
tcp是一个有状态的协议,在不同状态下只能做特定操作
开始监听就是将套接字状态置为listen状态,此时才能处理客户端请求
监听套接字只处理连接请求
链接创建后创建新套接字,所以要获取新连接,从监听套接字对应的新建连接队列中取出一个套接字,并返回其文件描述符
- 接收新连接:
对于客户端
- 创建流式套接字
- 不推荐绑定地址信息
- 发起连接
- 当服务端调用监听接口后,服务端和客户端就进行三次握手(三次握手在内核中完成,与程序员无关,服务端也不需要调用accept函数);
- 三次握手完毕,双方建立连接,将该连接从未完成连接队列中 放入 已完成队列;
- 服务端调用accept函数将该连接从已完成连接队列中拿出,产生新连接套接字;
TCP的发送和接收缓冲区
- 创建套接字后,就会有TCP的发送缓冲区和接收缓冲区;
- 在服务端发起新连接后,经三次握手,两端建立连接;
- 此时程序员调用accept函数,就会在服务端创建一个专用套接字,专门服务客户端;
- 原服务端套接字就在不断接收连接,将其称为 侦听套接字
多个服务端也会先和侦听套接字建立连接,服务端再调用accep函数创建新套接字
接口函数
1.socket函数
2.bind函数
3.listen,监听函数
- backlog是限制同一时刻,服务端能处理的连接数上限
限制同一时间有多少个客户端的连接请求能够被处理- 能和服务端建立连接的数量=backlog+1
4.connect,客户端连接函数
5.accept,服务端接收函数
当调用accept函数接收新连接的时候,如果已完成连接队列中没有新连接,则accept函数阻塞
6.send与recv,双方通信,发送与接收函数
- 对于recv函数,如果接收缓冲区中没有数据,调用recv去接收数据时函数会阻塞;
- 如果将新连接套接字设置成非阻塞属性,则调用recv函数时,即使接收缓冲区中没有数据,该函数也会返回
- 返回值的表现不是正常返回,而是出错返回
函数使用:
- accept是一个阻塞函数,是从内核中的已完成连接队列中,接收三次握手完成的连接;
- 调用accept后,如果已完成连接队列中没有三次握手的连接,函数就会阻塞;
- 将accept放入while循环中,每一次循环都是想接收一个新的连接,没有新连接函数就会阻塞;
- 将accept函数放在循环外确实可以解决再次阻塞问题,再来一个客户端,新客户端无法与服务端交流
- 新客户端确实连接上了服务端(三次握手连接已经建立),但是服务端没有调用accept函数
只能通过多线程解决