tcp和udp和黏包
阿新 • • 發佈:2020-12-20
Tcp建立連線的過程
server端
# import socket # # sk = socket.socket() #建立一個socket物件 # sk.bind(('127.0.0.1',8088)) #繫結ip地址和埠 # sk.listen() # while 1: # conn,addr = sk.accept() #等待建立連線 # #阻塞 直到連線建立才往下執行 # while 1: # ret = conn.recv(1024).decode('utf-8') #阻塞 知道收到 才往下執行 # print(ret) #if 'bye' in ret: # conn.send(b'bye') # break # info = input('>>>') # conn.send(info.encode('utf-8')) # # conn.close() #斷開連線 # sk.close() # 關閉socket物件 如果不關閉 仍能傳輸
client端
# import socket # sk = socket.socket() # sk.connect(('127.0.0.1',8088)) # #while 1: # msg = input('>>>') # sk.send(('client1'+msg).encode('utf-8')) # ret = sk.recv(1024).decode('utf-8') # print(ret) # if ret == 'bye': # sk.send(b'bye') # break # # sk.close()
Udp協議
server端
import socket sk = socket.socket(type=socket.SOCK_DGRAM) sk.bind(('127.0.0.1',8088)) while 1: msg,addr = sk.recvfrom(1024) print(addr) print(msg.decode('utf-8')) info = input(">>>").encode('utf-8') sk.sendto(info,addr) sk.close()
client端
import socket sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = (('127.0.0.1',8088)) while 1: info = input('1:') info = ('\033[34m來自1的訊息:%s\033[0m'%info).encode('utf-8') sk.sendto(info,ip_port) msg,addr = sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
黏包
黏包只存在tcp協議中,tcp內部優化演算法,報文分片傳輸,
黏包的原因:
1,傳送大於接收的位元組數,後續資訊會在下次傳送。
2,連續傳送短報文,tcp會自動處理成一段報文傳送
黏包的解決:借用struc模組
server端
# import socket # import struct # sk = socket.socket() # sk.bind(('127.0.0.1',8088)) # sk.listen() # # conn,addr = sk.accept() # while 1: # # cmd = input('>>>') # if cmd == 'q': # break # conn.send(cmd.encode('gbk')) # num = conn.recv(4) #接收4個位元組 # num = struct.unpack('i',num)[0] #轉成資料長度 # ret = conn.recv(int(num)).decode('gbk') # print(ret) # # conn.close() # sk.close()
client端
# import socket # import subprocess # import struct # sk = socket.socket() # sk.connect(('127.0.0.1',8088)) # while 1: # cmd = sk.recv(1024).decode('gbk') # if cmd == 'q': # break # res = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) # std_out = res.stdout.read() # std_err = res.stderr.read() # num = len(std_out)+len(std_err) # num_by = struct.pack('i',num) # sk.send(num_by) # sk.send(std_out) # sk.send(std_err) # sk.close()