1. 程式人生 > 實用技巧 >tcp和udp和黏包

tcp和udp和黏包

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()