Socketerve并发

基于tcp套接字,关键就是两个循环,一个链接循环,一个通讯循环

Socketserver模块中分两个大类:server类(解决链接问题)和request类(解决通信问题)

server类:

request类:

继承关系:

以下述代码为例,分析socketserver源码:

ftpserver=socketserver.ThreadingTCPServer(('127.0.0.1',8080),FtpServer)
ftpserver.serve_forever()

查找属性的顺序:

ThreadingTCPServer-->ThreadingMixIn-->TCPServer-->BaseServer

1.实例化得到tfpserver,先找类ThreadingTCPServer的_init_,在TCPServer中找到,进而执行Server_bind,server_active

2.找ftpsever下的server_forever,在BaseServer中找到,进而执行self._handle_request_noblock(),该方法同样是在BaseServer中

3.执行self._handle_request_noblcok()进而执行request,client_address=self.get_request()(就是TCPServer中的self.socket.accept()),然后执行self.process_request(request,client_address)

4.在ThreadingMiIn中找到process_request,开启多线程应对并发,进而执行process_request_thread,self.finish_request(request,client_address)

5.上述四部分完成了链接循环,本部分开始进入处理通讯部分,在BaseServer中找到finish_request,触发我们自己定义的类的实例化,去找_init_方法,而我们自己定义的类没有该方法,则去它的父类也就是BaseRequestHandler中找

源代码分析总结:

基于tcp的socketserver我们自己定义的类中的

1.self.server即套接字对象

2.self.request即一个链接

3.self.client_adderss即客户端地址

  1. #服务端:
  2. import socketserver
  3. class FTPserver(socketserver.BaseRequestHandler):#定义一个类 继承BaseRequestHandler #进行通讯
  4. def handle(self):
  5. # print(self)
  6. # print(self.request) #拿到一个conn链接循环
  7. while True: #通信循环
  8. data=self.request.recv(1024)
  9. print(data.decode("utf-8"))
  10. self.request.send(data.upper())
  11.  
  12. if __name__ == '__main__':
  13. obj=socketserver.ThreadingTCPServer(("127.0.0.1",8000),FTPserver) #自己的类名
  14. obj.serve_forever()#链接循环
  15.  
  16. #客户端1
  17. import socket
  18. s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  19. s.connect(("127.0.0.1",8000))
  20.  
  21. while True:
  22. msg=input(">>").strip()
  23. if not msg:continue
  24. s.send(msg.encode("utf-8"))
  25. data=s.recv(1024)
  26. s.close()
  27.  
  28. #客户端2
  29. import socket
  30. s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  31. s.connect(("127.0.0.1",8000))
  32.  
  33. while True:
  34. msg=input(">>").strip()
  35. if not msg:continue
  36. s.send(msg.encode("utf-8"))
  37. data=s.recv(1024)
  38. s.close()
  39.  
  40. #客户端3
  41. import socket
  42. s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  43. s.connect(("127.0.0.1",8000))
  44.  
  45. while True:
  46. msg=input(">>").strip()
  47. if not msg:continue
  48. s.send(msg.encode("utf-8"))
  49. data=s.recv(1024)
  50. s.close()

基于UDP的套接字

udp:sendto发消息,recvfrom收消息

udp是基于数据报

sendinto

sendinto(bytes_data,ip_port):发送数据报,bytes_data为空,还有ip_port,所有即便是发送空的bytes_data,数据报其实也不是空的,自己这端的缓冲区收到内容,操作系统就会控制udp协议发包

recvfrom

udp协议

(1)如果如果收消息缓冲区里的数据为“空”,recvfrom也会阻塞

(2)只不过udp协议的客户端sendinto一个空数据并不是真的空数据(包含:空数据+地址信息,得到的报仍然不会为空),所以客户端只要有一个sendinto(不管是否发送空数据,都不是真的空数据),服务端就可以recvfrom到数据。

(3)udp无链接

无链接,因而无需listen(backlog),更加没有什么连接池之说了

无链接,udp的sendinto不用管是否有一个正在运行的服务端,可以己端一个劲的发消息,只不过数据丢失

recvfrom收的数据小于sendinto发送的数据时,在mac和linux系统上数据直接丢失,在windows系统上发送的比接收的大直接报错

只有sendinto发送数据没有recvfrom收数据,数据丢失

udp套接字简单示例:

  1. #udp服务端
  2. import socket
  3. ip_port=("127.0.0.1",8000)
  4. buffer_size=1024
  5. udp_server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报
  6. udp_server.bind(ip_port)
  7. while True: #通信循环
  8. data,addr=udp_server.recvfrom(buffer_size)
  9. print(data.decode("utf-8"),addr)
  10. msg=input(">>:")
  11. udp_server.sendto(msg.encode("utf-8"),addr)
  12. udp_server.sendto(data.upper(),addr)
  13. udp_serve.close()
  14.  
  15. #udp客户端
  16. import socket
  17. ip_port=("127.0.0.1",8000)
  18. buffer_size=1024
  19. udp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报
  20. while True: #通信循环
  21. msg=input(">>:").strip()
  22. udp_client.sendto(msg.encode("utf-8"),ip_port) #每次发包都要指定端口
  23.  
  24. data,addr= udp_client.recvfrom(buffer_size)
  25. print(data.decode("utf-8"))
  26. udp_client.close()
  27.  
  28. #udp客户端1
  29. import socket
  30. ip_port=("127.0.0.1",8000)
  31. buffer_size=1024
  32. udp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报
  33. while True: #通信循环
  34. msg=input(">>:").strip()
  35. udp_client.sendto(msg.encode("utf-8"),ip_port) #每次发包都要指定端口
  36.  
  37. data,addr= udp_client.recvfrom(buffer_size)
  38. print(data.decode("utf-8"))
  39. udp_client.close()
  40.  
  41. #udp客户端2
  42.  
  43. import socket
  44. ip_port=("127.0.0.1",8000)
  45. buffer_size=1024
  46. udp_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报
  47. while True: #通信循环
  48. msg=input(">>:").strip()
  49. udp_client.sendto(msg.encode("utf-8"),ip_port) #每次发包都要指定端口
  50.  
  51. data,addr= udp_client.recvfrom(buffer_size)
  52. print(data.decode("utf-8"))
  53. udp_client.close()

python--socket/Socketerver并发/udp的更多相关文章

  1. Python Socket多线程并发

    1.SocketServer模块编写的TCP服务器端代码 Socketserver原理图 服务端: import SocketServer #导入SocketServer,多线程并发由此类实现 cla ...

  2. 老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具

    老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具 poptest是业内唯一的测试开发工程师培训机构,测试开发工程师主要是为测试服务开发测试工具,在工作中要求你做网络级别的安全 ...

  3. Python基于socket模块实现UDP通信功能示例

    Python基于socket模块实现UDP通信功能示例 本文实例讲述了Python基于socket模块实现UDP通信功能.分享给大家供大家参考,具体如下: 一 代码 1.接收端     import ...

  4. python socket原理 及socket如何使(tcp udp协议)

    网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. 建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API) 主要内容: 1.基于 ...

  5. python之多并发socket

    先看socket多并发的服务端的代码,这里是用多线程实现的多并发socketserver import socketserver # socketserver有四个基本的类,后两个不常用,这4个类处理 ...

  6. python之多并发socket(zz)

    本文转载自:http://www.cnblogs.com/bainianminguo/p/7337210.html 先看socket多并发的服务端的代码,这里是用多线程实现的多并发socketserv ...

  7. Python的网络编程[0] -> socket[2] -> 利用 socket 建立 TCP/UDP 通信

    Socket 目录 socket 的 TCP/IP 通信基本建立过程 socket 的 UDP 通信基本建立过程 socket 的 UDP 广播式通信基本建立过程 socket 的多线程通信建立过程 ...

  8. Python socket进阶 多线程/进程

    #首先,什么场合下用进程,什么场合下用线程: . 计算密集型的用进程. . IO密集型的用进程. xSocket语法及相关 Socket Families(地址簇) socket.AF_UNIX un ...

  9. python socket编程详细介绍

    Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中心类,可以简化网络 ...

随机推荐

  1. 51ak带你看MYSQL5.7源码2:编译现有的代码

    从事DBA工作多年 MYSQL源码也是头一次接触 尝试记录下自己看MYSQL5.7源码的历程 目录: 51ak带你看MYSQL5.7源码1:main入口函数 51ak带你看MYSQL5.7源码2:编译 ...

  2. 常用css样式颜色值: 64位真彩和256位值

    1. background-color: #eee; 2. background-color: #797979; 3. background-color: #007aff; 继续更新中

  3. 2017总结&2018展望

    2017已逝2018已来,是时候放下包袱来好好回顾下2017做了什么,有什么收获,遗憾之处的原因是什么.2018应该怎么做才能让自己满意,才能少一些遗憾. 2017 工作 工作中所参与的项目是一个直播 ...

  4. IMLite轻量级即时通信工具开发指南

    花了一周时间开发了一个简单的即时通信工具,勉强算是程序原型.现在我把开发流程和一些个人的想法记录下来.本文首先介绍程序架构和通信接口,之后会聚焦到服务器的信号槽设计原则,接下来将解释有关TCP通信的粘 ...

  5. 笔记:Spring Cloud Eureka 服务发现与消费

    服务发现与消费,其服务发现的任务是由Eureka的客户端完成,而服务的消费任务由Ribbon.JerseyClient等完成,Ribbon是一个基于HTTP和TCP的客户端负载均衡器:使用Jersey ...

  6. 笔记:Struts2 Action 非泛型集合元素类型转换

    局部类型转换文件 局部类型转换文件的文件名应为 ActionName-conversion.properties,其中 ActionName 是需要替换为 Action 的类名称,后面的 conver ...

  7. 在Node应用中避免“Dot Hell”

    转载自:http://blog.leapoahead.com/2015/09/03/prevent-node-require-dot-hell/ 在Node应用中,我们使用require来加载模块.在 ...

  8. Konckout第三个实例:循环绑定 -- table列表数据的填充

    传统js:拼接字符串,再写入指定标签中 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  9. SpringMVC参数校验

    使用SpringMVC时配合hibernate-validate进行参数的合法性校验,能节省一定的代码量. 使用步骤 1.搭建Web工程并引入hibernate-validate依赖 <depe ...

  10. java Classpath 的解读

    在了解java的classpath之前先来看看java的运行机制  1.首先是编译,将.java文件编译成虚拟机认识的二进制文件.这个过程需要的命令是javac  可以在jdk的bin目录中找到,ja ...