基于一个问题的引出:多进程、多线程、是可以实现多任务的,但它们的效率不高,耗费的资源多,在当下高并发压力下力不从心。单进程、单线程、协程的方式效率高消费的资源少,那么它是怎么实现多任务的呢?
核心点就是把代码中会阻塞的地方改为非阻塞,这样就不会是程序因为没有接收到客户端的请求或其他的一些问题而卡住不动,这样也就可以实现单进程、单线程、协程下的多任务。在设置非阻塞是是给阻塞位置的对象去设置。
tcp_server_socket.setblocking(False) #设计套接字为非阻塞的方式
由于当把阻塞位置设置成非阻塞,在没有客户端的请求时,由于它非阻塞,会产生错误,进而引起程序的奔溃,为了防止这样的事情发生,我们需要把改为非阻塞的地方加上异常保护既try~expect 这样当产生了错误时也能保护程序不奔溃 而只是返回一个没有请求的提示而已。
当receive既recv处既没有异常,又没有数据返回,就是它已经在这个地方调用了close ,它传输完了所有数据通过4次挥手端断开了连接 调用了close 。
recv不产生异常时有两种情况,一种是传来了数据,传来了数据就正常操作;另一种是对方调用了close 导致reccv返回,这样套接字也调用close 返回客户端已经关闭,这个时候就可以把客户端套接字从它所在的列表中移除了。
如果在程序中设置了一个时间间隔如0.5s ,那么在0.5s内如果快速传输数据,那么就可能使多个传输的数据都堆积在一行上,这是一个很危险的事情,这可能导致有黑客利用这一点来大量短时间传输垃圾数据来消耗服务器的资源,导致服务器的运行速度下降等不利情况出现。可以在不必要的时候关掉延时以提升系统运行速度。
用长连接实现非阻塞时,需要屏蔽掉socket.close 因为要多次使用同一个套接字来传输数据,这样就有一个问题,如何让系统明白数据传输完成了呢,要解决这一问题就需要在创建连接的头文件中加入connect_lenth:........#字符长度,这样就能让系统明白一次传输的数据长度,从而能实现非阻塞的长连接。