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服务器 进程 线程 非阻塞的更多相关文章

  1. 利用Python中SocketServer 实现客户端与服务器间非阻塞通信

    利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信 版权声明 本文转自:http://blog.csdn.net/cnmilan/article/details/9664823 ...

  2. 【python】网络编程-SocketServer 实现客户端与服务器间非阻塞通信

    利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信.首先,先了解下SocketServer模块中可供使用的类:BaseServer:包含服务器的核心功能与混合(mix-in)类 ...

  3. 阻塞IO、非阻塞IO、同步IO、异步IO等

    https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...

  4. 性能追击:万字长文30+图揭秘8大主流服务器程序线程模型 | Node.js,Apache,Nginx,Netty,Redis,Tomcat,MySQL,Zuul

    本文为<高性能网络编程游记>的第六篇"性能追击:万字长文30+图揭秘8大主流服务器程序线程模型". 最近拍的照片比较少,不知道配什么图好,于是自己画了一个,凑合着用,让 ...

  5. 非阻塞式I/O

    套接字的默认状态是阻塞的.这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待相应的操作完成.可能阻塞的套接字调用可分为以下4类 (1)输入操作,包括read,readv,recv ...

  6. 同步异步,阻塞非阻塞 和nginx的IO模型

    同步与异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication).所谓同步,就是在发出一个*调用*时,在没有得 ...

  7. I/O模型(同步、非同步、阻塞、非阻塞)总结

    I/O:同步(synchronous).异步(asynchronous).阻塞(blocking).非阻塞(nonblocking) 1.I/O内部机制 出于安全考虑,用户程序(用户态)是没办法直接操 ...

  8. (转)同步异步,阻塞非阻塞 和nginx的IO模型

    同步异步,阻塞非阻塞 和nginx的IO模型  原文:https://www.cnblogs.com/wxl-dede/p/5134636.html 同步与异步 同步和异步关注的是消息通信机制 (sy ...

  9. 【python】-- 事件驱动介绍、阻塞IO, 非阻塞IO, 同步IO,异步IO介绍

    事件驱动介绍 一.前言 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每收 ...

随机推荐

  1. 关于message pack as3 版本的一些修改。

    玩个人项目的时候,根据前辈的推荐开始用messagepack,分别是py版和as3版: 然后在github上找到了demonsters的as3模块,于是颠屁颠屁地拿来用了,用的时候发现了一些小地方过不 ...

  2. HDU 3038 How Many Answers Are Wrong 【YY && 带权并查集】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=3038 How Many Answers Are Wrong Time Limit: 2000/1000 ...

  3. fastJson简单实用

    public class FastJsonText { @Test public void text(){ User user1 = new User(); user1.setName("健 ...

  4. Python-Url编码和解码

    一.为什么要进行Url编码 url带参数的请求格式为(举例): http://www.baidu.com/s?k1=v1&k2=v2 当请求数据为字典data = {k1:v1, k2:v2} ...

  5. centos7 编译安装nginx1.16.0( 完整版 )

    一.安装依赖包 yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel 依赖包说明: 1.编译 ...

  6. 【luogu P2397 yyy loves Maths VI (mode) 】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2397 卡空间. 对于众数出现次数 > n/2 我们考虑rand. 每次正确的概率为1/2,五个测试点, ...

  7. 【luogu P3884 [JLOI2009]二叉树问题】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3884 对方不想和你说话并向你扔了一个lca模板. #include <cstdio> #incl ...

  8. java.lang.IllegalStateException: Circular dependencies cannot exist in RelativeLayout

    <TextView android:layout_width="fill_parent" android:layout_height="wrap_content&q ...

  9. Hive中使用LZO

    hive 中使用lzo 1 启动hive 错误Exception in thread "main" java.lang.NoClassDefFoundError: org/apac ...

  10. 【办公-Word-VB】人民币大写转换-带完整注释

    完整代码见:我的CSDN博客 -------------------- 应公司财务人员的请求,需在Word中做个:输入阿拉伯数字,自动转换成大写,并填充到Word控件中对应的亿.万.千控件格子的功能, ...