Loading

python/socketserver网络基础

python/socketserver网络基础

socket也就是套接字

  用于描述IP地址和端口,是一个通信链的句柄,可以用来实现 不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,

  同时提供几种服务,每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。           

连接原理

  根据连接启动的方式以及本地套接字要连接的目标,套接字之间的链接过程可以分为三个步骤:服务器监听,客户端请求,链接确认。

  (1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

  (2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述他要连接的服务器的套接字,

    指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

  (3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,

    把服务器套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

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

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

  server类:

 

 

  request类:

 

  继承关系:

 

 

 

 

 

以下代码为例,分析socketsever源码

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

差找属性的顺序:ThreadingTcpSeverde-ThreadingMixln-TCPServer-BaseServer

1.实例化得到ftpserver,先找类threadingTCPSever的__init__,在TCPServver中找到,进而执行server_bind,server_active

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

3.执行self._handle_request_noblock()进而执行request,client_address=self.get_requset()(就是TCPSever中的self.socket.accept()),然后执行self.process_request(request,client_address)

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

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

源码分析总结:

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

1.self.server 即套接字对象

2.self.request即一个链接

3.self.client_address及客户端地址

基于udp的socktserver我们自己定义的类中

1.self.request是一个元组(第一个元素是客户端发来数据,第二部分是服务端的udp套接字对象),如(b'adss',<socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8080)>)

2.self.client_address即客户端地址

通过sockserver模块进行多线程式

 1 TCP并发服务端
 2 import socketserver
 3 IP=('127.0.0.1',8080)
 4 class TCPserver(socketserver.BaseRequestHandler):  #通讯
 5     def handle(self):
 6         print(self)
 7         print(self.request)     #相当于conn
 8         while True:
 9             data=self.request.recv(1024)
10             print(data.decode('utf-8'))
11             dr=input(">>>>")
12             self.request.send(dr.encode('utf-8'))
13 
14 if __name__ == '__main__':
15     din=socketserver.ThreadingTCPServer(IP,TCPserver)
16     din.serve_forever()   #通讯循环
 1 TCP多并发客户端
 2 import socket
 3 IP=('127.0.0.1',8080)
 4 din=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 5 din.connect(IP)
 6 while True:
 7     inp=input('>>')
 8     if not inp:continue
 9     din.send(inp.encode('utf-8'))
10     data=din.recv(1024)
11     print(data.decode('utf-8'))
12 din.close()

通过sockserver模块进行多线程式

 1 UDP多并发服务端
 2 import socketserver
 3 ip=('127.0.0.1',8080)
 4 class UDPserver(socketserver.BaseRequestHandler):
 5     def handle(self):
 6         print(self)
 7         print(self.request)  #相当于conn
 8         de=self.request[0]
 9         print(de.decode('utf-8'))
10         # print(self.request[1])
11         cou=input('::::')
12         self.request[1].sendto(cou.encode('utf-8'),self.client_address)
13 
14 if __name__ == '__main__':
15     din=socketserver.ThreadingUDPServer(ip,UDPserver)
16     din.serve_forever()    #链接循环

 

 1 UDP多并发客户端
 2 import socket
 3 din=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 4 ip=('127.0.0.1',8080)
 5 while True:
 6     inp=input('>>')
 7     din.sendto(inp.encode('utf-8'),ip)
 8     data,addr=din.recvfrom(1024)
 9     print(data.decode('utf-8'))
10     
11 din.close()

 

posted @ 2017-05-05 17:53  Meet~  阅读(313)  评论(0编辑  收藏  举报