recv原理、高阶版黏包解决方案、基于UDP的socket通信
生活随笔
收集整理的這篇文章主要介紹了
recv原理、高阶版黏包解决方案、基于UDP的socket通信
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
recv原理、高階版黏包解決方案、基于UDP的socket通信
recv原理
源碼解釋: Receive up to buffersize bytes from the socket. 接收來自socket緩沖區的字節數據, For the optional flags argument, see the Unix manual. 對于這些設置的參數,可以查看Unix手冊。 When no data is available, block untilat least one byte is available or until the remote end is closed. 當緩沖區沒有數據可取時,recv會一直處于阻塞狀態,直到緩沖區至少有一個字節數據可取,或者遠程端關閉。 When the remote end is closed and all data is read, return the empty string. 關閉遠程端并讀取所有數據后,返回空字符串。 # 1,驗證服務端緩沖區數據沒有取完,又執行了recv執行,recv會繼續取值。 import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8080)) phone.send('hello'.encode('utf-8')) phone.close()# 2,驗證服務端緩沖區取完了,又執行了recv執行,此時客戶端20秒內不關閉的前提下,recv處于阻塞狀態。 import socket import time phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8080)) phone.send('hello'.encode('utf-8')) time.sleep(20)phone.close()# 3,驗證服務端緩沖區取完了,又執行了recv執行,此時客戶端處于關閉狀態,則recv會取到空字符串。 import socket import time phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8080)) phone.send('hello'.encode('utf-8')) phone.close() # 1,驗證服務端緩沖區數據沒有取完,又執行了recv執行,recv會繼續取值。import socketphone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)conn, client_addr = phone.accept() from_client_data1 = conn.recv(2) print(from_client_data1) from_client_data2 = conn.recv(2) print(from_client_data2) from_client_data3 = conn.recv(1) print(from_client_data3) conn.close() phone.close()# 2,驗證服務端緩沖區取完了,又執行了recv執行,此時客戶端20秒內不關閉的前提下,recv處于阻塞狀態。import socketphone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)conn, client_addr = phone.accept() from_client_data = conn.recv(1024) print(from_client_data) print(111) conn.recv(1024) # 此時程序阻塞20秒左右,因為緩沖區的數據取完了,并且20秒內,客戶端沒有關閉。 print(222)conn.close() phone.close()# 3 驗證服務端緩沖區取完了,又執行了recv執行,此時客戶端處于關閉狀態,則recv會取到空字符串。import socketphone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)conn, client_addr = phone.accept() from_client_data1 = conn.recv(1024) print(from_client_data1) from_client_data2 = conn.recv(1024) print(from_client_data2) from_client_data3 = conn.recv(1024) print(from_client_data3) conn.close() phone.close()# recv空字符串: 對方客戶端關閉了,且服務端的緩沖區沒有數據了,我再recv取到空bytes.高階版黏包解決方案
服務端:
import socket import subprocess import struct import jsonphone = socket.socket() phone.bind(('127.0.0.1',8897))phone.listen(3) print("等待接入") while 1:conn, addr = phone.accept()print(conn, addr)try:while 1:from_client_data = conn.recv(1024)if from_client_data.decode('utf-8').upper() == 'Q':print('對方中斷鏈接')breakobj = subprocess.Popen(from_client_data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)to_client_data = obj.stdout.read() + obj.stderr.read()total_size = len(to_client_data)dic = {'filename':'text1','MD5':120045318563413485631,'total_size':total_size}head1 = json.dumps(dic).encode('utf-8')len_head1 = len(head1)head_bytes = struct.pack('i',len_head1)conn.send(head_bytes)conn.send(head1)conn.send(to_client_data)except ConnectionError:print('對方中斷網絡鏈接')breakconn.close() phone.close()客戶端:
import socket import struct import json phone = socket.socket()phone.connect(('127.0.0.1',8897)) while 1:to_server_data = input('請輸入內容')phone.send(to_server_data.encode('utf-8'))if to_server_data.upper() == "Q":print('主動退出')breakif not to_server_data.strip():continuehead = phone.recv(4)num = struct.unpack('i',head)[0]dic_head = phone.recv(num).decode('utf-8')dic = json.loads(dic_head)s = b''while len(s) < dic['total_size']:from_server_data = phone.recv(1024)s += from_server_dataprint(s.decode('gbk')) phone.close()基于UDP的socket通信
服務端:
import socket udp_sk = socket.socket(type=socket.SOCK_DGRAM) #創建一個服務器的套接字 udp_sk.bind(('127.0.0.1',9000)) #綁定服務器套接字 msg,addr = udp_sk.recvfrom(1024) print(msg) udp_sk.sendto(b'hi',addr) # 對話(接收與發送) udp_sk.close() # 關閉服務器套接字客戶端:
import socket ip_port=('127.0.0.1',9000) udp_sk=socket.socket(type=socket.SOCK_DGRAM) udp_sk.sendto(b'hello',ip_port) back_msg,addr=udp_sk.recvfrom(1024) print(back_msg.decode('utf-8'),addr)轉載于:https://www.cnblogs.com/lifangzheng/p/11366039.html
總結
以上是生活随笔為你收集整理的recv原理、高阶版黏包解决方案、基于UDP的socket通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: socket补充:通信循环、链接循环、远
- 下一篇: 二次幂权限设计