使用Twisted框架将文件发送给客户端
我一直在寻找如何通过twisted框架将文件从服务器传输到客户端的方法,但一直没有找到有用的信息。
在我的情况下,我只是想给用户发送一张图片,这是一个聊天应用程序,我在本地[也就是我有服务器的地方]存储这张图片[或者说我正在尝试这么做]
这是我做的:
from twisted.internet import reactor
from twisted.internet.protocol import Factory , Protocol
class IphoneChat(Protocol):
def connectionMade(self):
self.factory.clients.append(self)
def connectionLost(self , reason):
self.factory.clients.remove(self)
def dataReceived(self,data):
a = data.split(':')
contor = 0
command = a[0]
content = a[1]
if command == "saveimage":
personName = a[1]
contentData = a[2]
escape = a[3]
location = "person-images/"+str(personName)+".jpg"
try:
f = open (location,'w+')
f.write(contentData)
except :
self.transport.write("error when opening the file")
elif command == "getimage" :
picture = a[1]
extra = a[2]
location = "person-images/"+picture+".png"
try:
self.transport.write("image:")
for bytes in read_bytes_from_file(location) :
self.transport.write(bytes)
self.transport.write('\r\n')
except :
self.transport.write('no such file\r\n')
factory = Factory()
factory.protocol=IphoneChat
factory.clients = []
reactor.listenTCP(8023,factory)
print "IPhone Chat server started"
reactor.run()
但是我在客户端[iOS应用]遇到了奇怪的情况,表现就是它没有正常工作。
这是iOS应用的一些内容:
var binaryData: NSData
let string : NSString = output.componentsSeparatedByString(":")[0] as NSString
binaryData = string.dataUsingEncoding(NSUTF8StringEncoding)!
var data = UIImage(data: binaryData)
self.personImage.image = data
self.personImage.hidden = true
问题出在服务器端还是客户端呢?
1 个回答
有一个明显的错误,不过我不能确定这是否是导致它“无法工作”的唯一原因:你的代码期望在一端调用 transport.write(x)
时,另一端会调用 dataReceived(self, x)
,而且 x
是相同的。这在TCP中并不总是这样。TCP提供的是一个字节流,你无法控制这个流是如何被分割的。你可以查看Twisted常见问题解答。举个例子,如果一端调用 transport.write('foobar')
,那么另一端可能会接收到两次调用:第一次是 dataReceived('foob')
,然后很快又是 dataReceived('ar')
。
你需要做的是实现一个合适的协议来在TCP流中传递消息。不过,我建议不要自己从头开始写,而是选择Twisted中包含的几种协议之一,或者使用其他明确规定的协议,比如websockets。
你似乎是用 '\r\n'
来结束消息,这是一种在字节流中分隔消息的策略,但请注意,你需要在接收端进行缓冲,以便收集完整的消息。这就是Twisted中包含的 LineReceiver
协议所做的事情。不过,如果你的 read_bytes_from_file()
函数如名字所示返回的是字节数据,那么如果图像数据中包含 '\r\n'
,你的协议就会出问题。
一些一般性的开发建议:一开始不要试图把Twisted服务器和iPhone客户端的完整实现拼凑在一起,然后发现它无法工作。你可能在客户端和服务器上都有更多的错误,但这都是正常的。写一些可以在同一台机器上轻松测试的代码。所以,确实要写一个简单的测试客户端在服务器上运行。添加调试打印或日志记录,以便查看发生了什么,比如打印 dataReceived(x)
被调用时的参数。