只有TCP会出现粘包,UDP不会。
引发粘包的两种场景:
1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据量很小,会合到一起,产生粘包)
2、接收方不及时接收缓冲区的包,造成多个包接收(服务端发送了一段数据,客户端只收了一小部分,客户端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
解决第一种场景的粘包(连续发送数据时,利用recv阻塞,等待客户端响应再继续发送)
服务端
#coding=utf-8 import socket import os server = socket.socket() server.bind(('localhost', 8888)) server.listen(5) while True: conn, address = server.accept() while True: rev = conn.recv(1024) if len(rev) == 0: break rev = os.popen(rev).read() conn.send(str(len(rev))) prompt_again = conn.recv(1024) # 等待客户端响应 print rev conn.send(rev or 'ok!') # 继续发消息 conn.close()
客户端(收到消息后,发送消息,通知服务端可以继续发送)
#coding=utf-8 import socket client = socket.socket() client.connect(('localhost', 8888)) while True: msg = raw_input('>>') if len(msg.strip()) == 0: continue client.send(msg) rev_len = client.recv(1024) print '服务器端消息长度:', rev_len client.send('again') # 通知服务器端可以继续发送 rev = client.recv(1024) print rev client.close()
解决第二种场景的粘包(服务器端在发送大量数据之前,先发送长度,客户端循环接收直至总数据长度不小于服务器端发送的长度值)
服务端
#coding=utf-8 import socket import os server = socket.socket() server.bind(('localhost', 9999)) server.listen(5) while True: conn, address = server.accept() while True: rev = conn.recv(1024) if len(rev) == 0: break if os.path.isfile(rev): size = os.stat(rev).st_size conn.send(str(size)) prompt_again = conn.recv(1024) f = open(rev) for line in f: conn.send(line) f.close() conn.close()
客户端
#coding=utf-8 import socket client = socket.socket() client.connect(('localhost', 9999)) while True: file_name = raw_input('>>') if len(file_name.strip()) == 0: continue client.send(file_name) rev_len = int(client.recv(1024)) client.send('again') len_now = 0 f = open(file_name + 'tmp', 'w') while len_now < rev_len: data = client.recv(1024) len_now += len(data) f.write(data) f.close() client.close()