12 TCP服务器 进程 线程 非阻塞
1.单进程服务器
from socket import * serSocket = socket(AF_INET, SOCK_STREAM) # 重复使用绑定的信息
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1) localAddr = ('', 7788) serSocket.bind(localAddr) serSocket.listen(5) while True: print('-----主进程,,等待新客户端的到来------') newSocket,destAddr = serSocket.accept() print('-----主进程,,接下来负责数据处理[%s]-----'%str(destAddr)) try:
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print('recv[%s]:%s'%(str(destAddr), recvData))
else:
print('[%s]客户端已经关闭'%str(destAddr))
break
finally:
newSocket.close() serSocket.close()

总结
- 同一时刻只能为一个客户进行服务,不能同时为多个客户服务
- 类似于找一个“明星”签字一样,客户需要耐心等待才可以获取到服务
- 当recv接收数据时,返回值为空,即没有返回数据,那么意味着客户端已经调用了close关闭了;因此服务器通过判断recv接收数据是否为空 来判断客户端是否已经下线
2.如何实现并发的?

from socket import *
from multiprocessing import Pool serSocket = socket(AF_INET, SOCK_STREAM)
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
#1表示端口可以充分使用,不会出现already used
localAddr = ('', 7788)
serSocket.bind(localAddr)
serSocket.listen(5) def dealWithClient(newSocket,destAddr):
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print('recv[%s]:%s'%(str(destAddr), recvData))
else:
print('[%s]客户端已经关闭'%str(destAddr))
break
newSocket.close() def main():
while True:
print('-----主进程,,等待新客户端的到来------')
newSocket,destAddr = serSocket.accept()
print('-----主进程,,接下来负责数据处理[%s]-----'%str(destAddr)) client = Pool(targetc=dealWithClient,args=(newSocket,destAddr))
client.start() newSocket.close() #新的进程以及有套接字,此时的套接字,不需要了 serSocket.close() if __name__ == "__main__":
main()
3. 多进程服务器:进程占用的资源多
from socket import *
from multiprocessing import *
from time import sleep # 处理客户端的请求并为其服务
def dealWithClient(newSocket,destAddr):
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print('recv[%s]:%s'%(str(destAddr), recvData))
else:
print('[%s]客户端已经关闭'%str(destAddr))
break newSocket.close() def main(): serSocket = socket(AF_INET, SOCK_STREAM)
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
localAddr = ('', 7788)
serSocket.bind(localAddr)
serSocket.listen(5) try:
while True:
print('-----主进程,,等待新客户端的到来------')
newSocket,destAddr = serSocket.accept() print('-----主进程,,接下来创建一个新的进程负责数据处理[%s]-----'%str(destAddr))
client = Process(target=dealWithClient, args=(newSocket,destAddr))
client.start() #因为已经向子进程中copy了一份(引用),并且父进程中这个套接字也没有用处了
#所以关闭
newSocket.close()
finally:
#当为所有的客户端服务完之后再进行关闭,表示不再接收新的客户端的链接
serSocket.close() if __name__ == '__main__':
main()
- 通过为每个客户端创建一个进程的方式,能够同时为多个客户端进行服务
- 当客户端不是特别多的时候,这种方式还行,如果有几百上千个,就不可取了,因为每次创建进程等过程需要好较大的资源

- 写时copy:进程先调用,不到万不得已,才copy一份

4.多线程服务器:线程共用同一份进程资源
#coding=utf-8
from socket import *
from threading import Thread
from time import sleep # 处理客户端的请求并执行事情
def dealWithClient(newSocket,destAddr):
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print('recv[%s]:%s'%(str(destAddr), recvData))
else:
print('[%s]客户端已经关闭'%str(destAddr))
break newSocket.close() def main(): serSocket = socket(AF_INET, SOCK_STREAM)
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
localAddr = ('', 7788)
serSocket.bind(localAddr)
serSocket.listen(5) try:
while True:
print('-----主进程,,等待新客户端的到来------')
newSocket,destAddr = serSocket.accept() print('-----主进程,,接下来创建一个新的进程负责数据处理[%s]-----'%str(destAddr))
client = Thread(target=dealWithClient, args=(newSocket,destAddr))
client.start() #因为线程中共享这个套接字,如果关闭了会导致这个套接字不可用,
#但是此时在线程中这个套接字可能还在收数据,因此不能关闭
#newSocket.close()
finally:
serSocket.close() if __name__ == '__main__':
main()
- 模拟tcp客户端,多线程可以连接

5.单进程服务器:非阻塞模式
#将套接字设置为非堵塞
#设置为非堵塞后,如果accept时,恰巧没有客户端connect,那么accept会
#产生一个异常,所以需要try来进行处理
serSocket.setblocking(False)
from socket import *
#1.创建socket
serSocket = socket(AF_INET, SOCK_STREAM) #2. 绑定本地ip以及port
localAddr = ('', 7788)
serSocket.bind(localAddr) #3. 让这个socket 变为非堵塞
serSocket.setblocking(False) #4. 将socket变为监听(被动)套接字
serSocket.listen(100) # 用来保存所有已经连接的客户端的信息
clientAddrList = [] while True: #等待一个新的客户端的到来(即完成3次握手的客户端)
try:
clientSocket,clientAddr = serSocket.accept()
except:
pass
else:
print("一个新的客户端到来:%s"%str(clientAddr))
clientSocket.setblocking(False)
clientAddrList.append((clientSocket,clientAddr)) for clientSocket,clientAddr in clientAddrList:
try:
recvData = clientSocket.recv(1024)
except:
pass
else:
if len(recvData)>0:
print("%s:%s"%(str(clientAddr), recvData))
else:
clientSocket.close()
clientAddrList.remove((clientSocket, clientAddr))
print("%s 已经下线"%str(clientAddr))

12 TCP服务器 进程 线程 非阻塞的更多相关文章
- 利用Python中SocketServer 实现客户端与服务器间非阻塞通信
利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信 版权声明 本文转自:http://blog.csdn.net/cnmilan/article/details/9664823 ...
- 【python】网络编程-SocketServer 实现客户端与服务器间非阻塞通信
利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信.首先,先了解下SocketServer模块中可供使用的类:BaseServer:包含服务器的核心功能与混合(mix-in)类 ...
- 阻塞IO、非阻塞IO、同步IO、异步IO等
https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...
- 性能追击:万字长文30+图揭秘8大主流服务器程序线程模型 | Node.js,Apache,Nginx,Netty,Redis,Tomcat,MySQL,Zuul
本文为<高性能网络编程游记>的第六篇"性能追击:万字长文30+图揭秘8大主流服务器程序线程模型". 最近拍的照片比较少,不知道配什么图好,于是自己画了一个,凑合着用,让 ...
- 非阻塞式I/O
套接字的默认状态是阻塞的.这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待相应的操作完成.可能阻塞的套接字调用可分为以下4类 (1)输入操作,包括read,readv,recv ...
- 同步异步,阻塞非阻塞 和nginx的IO模型
同步与异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication).所谓同步,就是在发出一个*调用*时,在没有得 ...
- I/O模型(同步、非同步、阻塞、非阻塞)总结
I/O:同步(synchronous).异步(asynchronous).阻塞(blocking).非阻塞(nonblocking) 1.I/O内部机制 出于安全考虑,用户程序(用户态)是没办法直接操 ...
- (转)同步异步,阻塞非阻塞 和nginx的IO模型
同步异步,阻塞非阻塞 和nginx的IO模型 原文:https://www.cnblogs.com/wxl-dede/p/5134636.html 同步与异步 同步和异步关注的是消息通信机制 (sy ...
- 【python】-- 事件驱动介绍、阻塞IO, 非阻塞IO, 同步IO,异步IO介绍
事件驱动介绍 一.前言 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每收 ...
随机推荐
- 20165322 实验三 敏捷开发与XP实践
实验三 敏捷开发与XP实践 安装alibaba 插件,解决代码中的规范问题 根据老师的教程:打开Settings ->Plugins -> Browse repositories...在搜 ...
- javaw.exe 和java.exe的区别
1.java启动的程序是命令行程序或阻塞程序,如果该程序未执行完毕或未被关闭,则所打开的命令行将被阻塞,不能执行其它命令如dir等,可以通过Ctrl+C等方式关闭程序:2.javaw启动的程序是窗口程 ...
- 43. Multiply Strings 字符串相乘
1. 原始题目 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 示例 1: 输入: num1 = "2&qu ...
- 【luogu P2146 [NOI2015]软件包管理器】 题解
题目链接:https://www.luogu.org/problemnew/show/P2146 变量名真毒瘤 我真的再也不把l,left,r,right弄反了 反向思维更好做一些 #include ...
- HDU 1045 Fire Net(dfs,跟8皇后问题很相似)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others) ...
- Eclipse插件的卸载和安装
Eclipse 卸载插件: 右下角会有卸载进度 卸载完后 然后需要重启 Eclipse安装插件 选择本地下载好的插件 点击 Ok 插件下载地址:https://jaist.dl.sourceforge ...
- c语言描述的静态查找表
顺序表的查找: 直接循环依次和目标比较就行 有序表的查找(二分查找): int search(SS *T,Type key){ int mid; ; int high=T.length; while( ...
- 固定导航栏demo
代码如下 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...
- Viewpager实现今日头条顶部导航的功能
利用简单的Textview 和Viewpager实现滑动.点击换页的效果,效果图如下: 先上布局文件代码: <?xml version="1.0" encoding=&quo ...
- springboot2.04+mybatis-plus+swagger2+CodeGenerator
@author zhangyh SpringBoot技术栈搭建个人博客[项目准备] RESTful API就是一套协议来规范多种形式的前端和同一个后台的交互方式 原型设计 事实上,我是直接先去找的原 ...