OSI七层模型 
 
每层运行常见物理设备 
七层协议数据传输的封包与解包过程 
TCP三握四挥 
socket层 
数据传输动图如下: 
socket工作流程
socker()模块用法简单版本 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import  socketserver_test = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_test.bind(('127.0.0.1' , 8080 )) server_test.listen(5 ) conn, client_address = server_test.accept() print (client_address)data = conn.recv(1024 )   print (data)conn.send(data.upper()) conn.close() server_test.close() 
 
1 2 3 4 5 6 7 8 9 10 11 12 import  socketclient_test = socket.socket(sockrt.AF_INET, socket.SOCK_STREAM) client_test.connect(("127.0.0.1" , 8080 )) client_test.send('hello' .encode('utf8' )) data = client_test.recv(1024 ) print (data.decode('utf8' ))client_test.close() 
 
处理服务端连接不断 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import  socketserver_test = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_test.bind(("127.0.0.1" , 8080 )) server_test.listen(5 ) while  True :    conn, client_address = server_test.accept()     print (client_address)          while  True :         try :             data = conn.recv(1024 )             if  len (data) == 0 :                 break              print (data)             conn.send(data.upper())         except  Exception:             break      conn.close() server_test.close() 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import  socketclient_test = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_test.connect(('127.0.0.1' , 8080 )) while  True :    msg = input ('>>>:' ).strip()     if  len (msg) == 0 :         continue      client_test.send(msg.encode('utf8' ))     data = client_test.recv(1024 )     print (data.decode('utf8' )) client_test.close() 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 s.bind()    绑定(主机,端口号)到套接字 s.listen()  开始TCP监听 s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来 s.connect()     主动初始化TCP服务器连接 s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 s.recv()            接收TCP数据 s.send()            发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完) s.sendall()         发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完) s.recvfrom()        接收UDP数据 s.sendto()          发送UDP数据 s.getpeername()     连接到当前套接字的远端的地址 s.getsockname()     当前套接字的地址 s.getsockopt()      返回指定套接字的参数 s.setsockopt()      设置指定套接字的参数 s.close()           关闭套接字 s.setblocking()     设置套接字的阻塞与非阻塞模式 s.settimeout()      设置阻塞套接字操作的超时时间 s.gettimeout()      得到阻塞套接字操作的超时时间 s.fileno()          套接字的文件描述符 s.makefile()        创建一个与该套接字相关的文件 
 
粘包问题 远程执行shell命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import  socketimport  subprocessserver_test = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_test.bind(("127.0.0.1" , 8080 )) server_test.listen(5 ) while  True :    conn, client_address = server_test.accept()     print (client_address)          while  True :         try :             cmd = conn.recv(1024 )             if  len (cmd) == 0 :                 break              res = subprocess.Popen(cmd,                                    shell=True ,                                    stdout=subprocess.PIPE,                                    stderr=subprocess.PIPE)             res1 = res.stdout.read()             res2 = res.stderr.read()             conn.send(res1 + res2)         except  Exception:             break      conn.close() server_test.close() 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import  socketclient_test = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_test.connect(('127.0.0.1' , 8080 )) while  True :    msg = input ('>>>:' ).strip()     if  len (msg) == 0 :         continue      client_test.send(msg.encode('utf8' ))     data = client_test.recv(1024 )     print (data.decode('utf8' ))   client_test.close() 
 
客户端执行命令
 
粘包现象 
只有TCP有粘包现象,UDP永远不会粘包 粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的
 
两种粘包情况 
发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包) 
接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)  
 
解决粘包 
为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据
 
struct模块  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import  struct, jsonheader_dic = {'total_size' : 10241321431312 }   header_json = json.dumps(header_dic)   print (header_json)  print (len (header_json))  header_total_size = struct.pack('i' , len (header_json))   print (len (header_total_size))  header_upk = struct.unpack('i' , header_total_size) print (header_upk)  
 
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import  socket, struct, jsonimport  subprocesss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('127.0.0.1' , 8080 )) s.listen(5 ) while  True :    conn, address = s.accept()     print (address)     while  True :         try :             cmd = conn.recv(1024 )             if  len (cmd) == 0 :                 break              res = subprocess.Popen(cmd, shell=True ,                                    stdout=subprocess.PIPE,                                    stderr=subprocess.PIPE)             res1 = res.stdout.read()             res2 = res.stderr.read()             header_dic = {'total_size' : len (res1) + len (res2)}               header_json = json.dumps(header_dic)               header_bytes = header_json.encode('utf8' )               header = struct.pack('i' , len (header_bytes))               conn.send(header)             conn.send(header_bytes)               conn.send(res1)             conn.send(res2)         except  Exception:             break      conn.close() 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import  socket, struct, jsonc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) c.connect(('127.0.0.1' , 8080 )) while  True :    msg = input ('>>>: ' ).strip()     if  len (msg) == 0 :         continue      c.send(msg.encode('utf8' ))     header_bytes_len = struct.unpack('i' , c.recv(4 ))[0 ]       header_bytes = c.recv(header_bytes_len)       header_json = header_bytes.decode('utf8' )       header_dic = json.loads(header_json)       total_size = header_dic['total_size' ]       recv_size = 0      res = b''      while  recv_size < total_size:         data = c.recv(1024 )           recv_size += len (data)         res += data       print (res.decode('utf8' )) c.close() 
 
UDP协议套接字 1 2 3 4 5 6 7 8 9 10 11 12 import  sockets = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind(('127.0.0.1' , 9999 )) while  True :    data, address = s.recvfrom(1024 )     print (data, address)     s.sendto(data.upper(), address) 
 
1 2 3 4 5 6 7 8 9 10 import  socketc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while  True :    msg = input ('>>>: ' ).strip()     c.sendto(msg.encode('utf8' ), ('127.0.0.1' , 9999 ))     res, s_address = c.recvfrom(1024 )     print (res.decode('utf8' ), s_address) 
 
socketserver模块实现并发
基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环
socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)
 
server类:
request类:
TCP并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import  socketserverclass  MyRequestHandler (socketserver.BaseRequestHandler ):    def  handle (self ):         while  True :             try :                 data = self.request.recv(1024 )                 if  len (data) == 0 :                     break                  print (data)                 self.request.send(data.upper())             except  Exception:                 break          self.request.close() server = socketserver.ThreadingTCPServer(('127.0.0.1' , 8080 ), MyRequestHandler, bind_and_activate=True ) server.serve_forever() 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import  socketc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) c.connect(('127.0.0.1' , 8080 )) while  True :    msg = input ('>>>: ' ).strip()     if  len (msg) == 0 :         continue      c.send(msg.encode('utf8' ))     data = c.recv(1024 )     print (data.decode('utf8' )) c.close() 
 
UDP并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import  socketserverclass  MyRequesthanlder (socketserver.BaseRequestHandler ):         def  handle (self ):                    data,server = self.request                         server.sendto(data.upper(),self.client_address) server = socketserver.ThreadingUDPServer(('127.0.0.1' ,9999 ),MyRequesthanlder) server.serve_forever() from  socket import  *client = socket(AF_INET,SOCK_DGRAM) while  True :    msg = input (">>>>:" ).strip()     client.sendto(msg.encode('utf-8' ),('127.0.0.1' ,9999 ))     res,server_addr = client.recvfrom(1024 )     print (res.decode('utf-8' ))