最近在使用
python開發(fā)
一個(gè)通用的tcpclient
測(cè)試小工具。在使用
socket
進(jìn)行網(wǎng)絡(luò)編程中,如何判定對(duì)端發(fā)送一條報(bào)文是否接收完成,是進(jìn)行
socket
網(wǎng)絡(luò)開發(fā)必須要考慮的一個(gè)問題。這里,簡要介紹一下判別數(shù)據(jù)接收接收完成常用的三種方法:
1.基礎(chǔ)數(shù)據(jù)接收法:
使用基礎(chǔ)數(shù)據(jù)接收法時(shí),當(dāng)與服務(wù)socket
斷開連接時(shí),會(huì)接收到空字符串。因此,可以根據(jù)此特點(diǎn),在程序中加入循環(huán),一直接收數(shù)據(jù),直到數(shù)據(jù)發(fā)送端關(guān)閉
socket
連接。適用場景:客戶端和服務(wù)器的鏈接為 短鏈接(即一次
socket
通訊后連接就會(huì)關(guān)閉)。 代碼如下:
1
import socket,struct,sys,time
2
3 Port=22220
4 #assume a socket disconnect (data returned is empty string) means all data was #done being sent.
5
def
recv_basic(the_socket):
6 total_data=[]
7
while
True:
8 data = the_socket.recv(20480)
9
if
not data:
break
10 total_data.append(data)
11
return ''.join(total_data)
2.尾標(biāo)識(shí)方法
通過尋找接收的協(xié)議數(shù)據(jù)中的尾標(biāo)識(shí)字符串,獲取完整的數(shù)據(jù)的數(shù)據(jù)報(bào)文。適用場景:接收的協(xié)議數(shù)據(jù)中包含相關(guān)的尾標(biāo)識(shí)。代碼如下:
1 End='something useable as an end marker'
2
def
recv_end(the_socket):
3 total_data=[];data=''
4
while
True:
5 data=the_socket.recv(8192)
6
if End
in data:
7 total_data.append(data[:data.find(End)])
8
break
9 total_data.append(data)
10
if len(total_data)>1:
11 #check if end_of_data was split
12 last_pair=total_data[-2]+total_data[-1]
13
if End
in last_pair:
14 total_data[-2]=last_pair[:last_pair.find(End)]
15 total_data.pop()
16
break
17
return ''.join(total_data)
3.負(fù)載長度方法
即通過協(xié)議數(shù)據(jù)中的負(fù)載長度值,確定有效報(bào)文的長度,適用場景:協(xié)議數(shù)據(jù)中包含負(fù)載協(xié)議字段。這種方法也是比較常用和通用的一種方法,但是需要一邊接收數(shù)據(jù)一邊解析數(shù)據(jù)。代碼如下:
1
def
recv_size(the_socket):
2 #data length is packed into 4 bytes
3 total_len=0;total_data=[];size=sys.maxint
4 size_data=sock_data='';recv_size=8192
5
while total_len<size:
6 sock_data=the_socket.recv(recv_size)
7
if
not total_data:
8
if len(sock_data)>4:
9 size_data+=sock_data
10 size=struct.unpack('>i', size_data[:4])[0]
11 recv_size=size
12
if recv_size>524288:recv_size=524288
13 total_data.append(size_data[4:])
14
else:
15 size_data+=sock_data
16
else:
17 total_data.append(sock_data)
18 total_len=sum([len(i)
for i
in total_data ])
19
return ''.join(total_data)
來源:
博客園