Sockets 我的代码中有一个简单的ftp错误
Sockets 我的代码中有一个简单的ftp错误,sockets,python-2.6,Sockets,Python 2.6,我在底部运行代码时遇到错误。它就像一个简单的ftp。 我使用python2.6.6和CentOS 6.8版 在大多数linux服务器中,它都会得到如下正确结果:(非常抱歉,我刚刚注册,无法注册) 克林特: [root@Test ftp]# python client.py path:put|/home/aaa.txt 服务器: [root@Test ftp]# python server.py connected... pre_data:put|aaa.txt|4 cmd: put fil
我在底部运行代码时遇到错误。它就像一个简单的ftp。
我使用python2.6.6和CentOS 6.8版
在大多数linux服务器中,它都会得到如下正确结果:(非常抱歉,我刚刚注册,无法注册)
克林特:
[root@Test ftp]# python client.py
path:put|/home/aaa.txt
服务器:[root@Test ftp]# python server.py
connected...
pre_data:put|aaa.txt|4
cmd: put
file_name: aaa.txt
file_size: 4
upload successed.
但是我在某些服务器上出错(比如我个人电脑上的虚拟机)。我做了很多测试(python2.6/python2.7、Centos6.5/Centos6.7),发现这个错误并不是因为它们。以下是错误信息:[root@Lewis-VM ftp]# python server.py
connected...
pre_data:put|aaa.txt|7sdfsdf ###Here gets the wrong result, "sdfsdf" is the content of /home/aaa.txt and it shouldn't be sent here to 'file_size' and so it cause the "ValueError" below
cmd: put
file_name: aaa.txt
file_size: 7sdfsdf
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 10699)
Traceback (most recent call last):
File "/usr/lib64/python2.6/SocketServer.py", line 570, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib64/python2.6/SocketServer.py", line 332, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib64/python2.6/SocketServer.py", line 627, in __init__
self.handle()
File "server.py", line 30, in handle
if int(file_size)>recv_size:
ValueError: invalid literal for int() with base 10: '7sdfsdf\n'
此外,我发现如果我在client.py中的sk.send(cmd+“|”+file_name+“|”+str(file_size))
和sk.send(data)
之间插入time.sleep(1),错误就会消失。我已经说过,我在不同的系统和python版本中进行了测试,错误并不是因为它们。我猜这是因为一些系统配置?我检查了python.org中的socket.send()和socket.recv(),但没有任何帮助。有人能帮我解释一下为什么会这样吗?
代码如下:
#!/usr/bin/env python
#coding:utf-8
################
#This is server#
################
import SocketServer
import os
class MyServer(SocketServer.BaseRequestHandler):
def handle(self):
base_path = '/home/ftp/file'
conn = self.request
print 'connected...'
while True:
#####receive pre_data: we should get data like 'put|/home/aaa|7'
pre_data = conn.recv(1024)
print 'pre_data:' + pre_data
cmd,file_name,file_size = pre_data.split('|')
print 'cmd: ' + cmd
print 'file_name: '+ file_name
print 'file_size: '+ file_size
recv_size = 0
file_dir = os.path.join(base_path,file_name)
f = file(file_dir,'wb')
Flag = True
####receive 1024bytes each time
while Flag:
if int(file_size)>recv_size:
data = conn.recv(1024)
recv_size+=len(data)
else:
recv_size = 0
Flag = False
continue
f.write(data)
print 'upload successed.'
f.close()
instance = SocketServer.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
instance.serve_forever()
TCP是一个数据流。这就是问题所在。TCP不需要保持消息边界。所以当客户打电话给
connection.send("0123456789")
connection.send("ABCDEFGHIJ")
然后是一个幼稚的服务器,比如
while True;
data = conn.recv(1024)
print data + "_"
可打印以下任何内容:
0123456789_ABCDEFGHIJ_
0123456789ABCDEFGHIJ_
0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F_G_H_I_J_
服务器没有机会识别客户端调用了多少发送,因为客户端的TCP堆栈刚刚将数据插入到流中,并且服务器必须能够处理在不同于客户端使用的缓冲区中接收的数据
您的服务器必须包含用于分隔标头和数据的逻辑。所有基于TCP的应用程序协议都使用一种机制来识别应用程序级边界。例如,HTTP以空行分隔头和正文,并在单独的头中通知正文长度
当服务器在单独的缓冲区中接收到带有命令、名称和大小的标头时,程序正常工作。当客户端速度足够快并将数据快速推入流中,并且服务器读取一个区块中的标头和数据时,程序会失败。TCP是一个数据流。这就是问题所在。TCP不需要保持消息边界。所以当客户打电话给
connection.send("0123456789")
connection.send("ABCDEFGHIJ")
然后是一个幼稚的服务器,比如
while True;
data = conn.recv(1024)
print data + "_"
可打印以下任何内容:
0123456789_ABCDEFGHIJ_
0123456789ABCDEFGHIJ_
0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F_G_H_I_J_
服务器没有机会识别客户端调用了多少发送,因为客户端的TCP堆栈刚刚将数据插入到流中,并且服务器必须能够处理在不同于客户端使用的缓冲区中接收的数据
您的服务器必须包含用于分隔标头和数据的逻辑。所有基于TCP的应用程序协议都使用一种机制来识别应用程序级边界。例如,HTTP以空行分隔头和正文,并在单独的头中通知正文长度
当服务器在一个单独的缓冲区中接收到带有命令、名称和大小的标头时,程序正常工作。当客户端速度足够快并将数据快速推送到流中,并且服务器读取一个区块中的标头和数据时,程序会失败