问题:写了一个传输文件的小程序, 程序很简单, 原理就是服务器端启动一个server等待接受文件, 客户端通过socket连到server上,然后send文件。
服务器代码 server.py
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.listen(1)
clientSock, addr = self.sock.accept()
data = cSock.recv(4)
fileLen = struct.unpack('i', data)[0]
outfile = open('outputfile.txt', 'w')
while fileLen > 0 :
readLen = 1024
if fileLen < readLen: readLen = fileLen
data = clientSock.recv(readLen)
outfile.write(data)
<span style="color:#ff0000;">fileLen -= readLen</span>
outfile.close()
客户端代码client.py:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((serverIp, serverPort))
inputfiledata = open('input.txt').read()
inputfiledataLen = len(inputfiledata)
data = struct.pack('i', inputfiledataLen)
sock.send(data)
while inputfiledataLen > 0:
readLen = 1024
if inputfiledataLen < readLen: readLen = inputfiledataLen
sock.send(inputfiledata[:readLen])
inputfiledataLen -= readLen
inputfiledata = inputfiledata[readLen:]
sock.close()
前面用着一切正常那个, 偶尔有一次传输了一个几M大小的文件, 问题就出现了, 服务器端接受到的文件竟然不完整,后面少了几千行。
首先怀疑是不是tcp传输数据过程中丢失的, 上网查资料,发现tcp是安全的, tcp的滑动窗口机制和校验机制保证了,传到服务器端的数据肯定是完整的而且是正确的,通过tcpdump抓包验证,所有的数据确实都已经传输到了服务器端。
那问题肯定处在了server.py的while循环里, 通过跟踪发现while循环中的data大小并不等于readLen, 我们给出的recv的Length并不一定是返回数据的长度, 他只是返回数据的最大Length, 所以红色字体部分就出问题了,改成fileLen -= Len(data),问题就解决了。