2012-12-14 42 views
3
以簡單扭曲服務器實現接收長數據(> 1024bytes)

I'm有問題。 從一開始,我就開發一個必須與扭曲的服務器同步的ios應用程序。我準備將信息以JSON格式發送。然後我開始發送大塊數據(現在大概是256bytes + 4 bytes的命令 - 是的,我正在執行我自己的協議)。連接沒問題,我在我的服務器上收到這些數據包(在我自己的協議子類的dataReceived函數中)。 ios方法:NSInteger writtenBytes =[self.outputStream write:[data bytes] maxLength:[data length]]將寫入的字節返回到流中。對於前4個數據包,返回值是預期的(260字節)。如果我有更多可用的字節發送,下一次我調用該方法時,它會返回0(該蘋果文檔說:"If the receiver is a fixed-length stream and has reached its capacity, 0 is returned.")。扭曲緩衝器滿中的TCP連接

所以我推斷,輸入緩衝區已滿。我不知道如何釋放緩衝區(我不知道如何到達緩衝區)。我不知道緩衝區的限制在哪裏(在我看來,這幾乎是荒謬的)。

這是服務器(只用於基於字符串中協議的基礎這一問題的重要的東西)的基本測試

from twisted.internet.protocol import Protocol, Factory 
from twisted.internet import reactor 
class IphoneSync(Protocol): 
    def __init__(self): 
     self.__buffer = "" 

    def connectionMade(self): 
     self.transport.write("0:") 
     self.factory.clients.append(self) 
     print "clients are ", self.factory.clients 

    def connectionLost(self, reason): 
     self.factory.clients.remove(self) 

    def dataReceived(self, data): 

     #print "data is ", data 

     a = data.split(':') 
     if len(a) > 1: 
      command = a[0] 
      content = a[1] 

      msg = "" 
      if command == "iam": 
       #user&Pass checking 
       msg = "1" 


      elif command == "msg": 
       self.__buffer += data 

       msg = "1: continue" 

      elif command == "fin": 
       #procesaremos todo 
       #Convertir datos en json 
       #insertar/actualizar data en sqlite 
       #devolver respuesta 
       print "buffer is", self.__buffer 
       msg = "2: procesing" 

      print msg 
      self.transport.write(msg)  
      #for c in self.factory.clients: 
       #c.message(msg) 

    def message(self, message): 
     self.transport.write(message) 
     #self.transport.write(message + '\n') 


factory = Factory() 
factory.protocol = IphoneSync 
factory.clients = [] 
dir(factory) 

reactor.listenTCP(8000, factory) 
print "Iphone Chat server started" 
reactor.run() 

只見LineReceiver類,但我可不是發送線。傳輸的數據可能非常大(10Mb-50Mb)。我正在考慮使用Consumer/Producer模型,或RPC Protocols(AMP或PB)作爲解決方案,但我想用自己的協議工作。 如果有人知道如何幫助我,我會非常感激。不管怎麼說,還是要謝謝你。

回答

2

連接沒問題,我在我的服務器上收到這些數據包(在我自己的協議子類的dataReceived函數中)。

可能不是。 TCP是一種「面向流」的協議。您的應用程序的使用不是以數據包而是以字節序列來表示。無法保證dataReceived將與您傳遞給outputStream write的相同字符串一起被調用。如果你寫「你好,世界」,dataReceived可以用「你好,世界」被稱爲 - 或者可以調用兩次,先用「你好」,然後用「世界」。或者它可能被稱爲12次:第一個「h」,然後是「e」,然後是「l」等。

如果你打電話outputStream write兩次,一次用「hello」,一次用「world」完全有可能dataReceived將被稱爲「你好,世界」一次。或者也許兩次,但是用「h」然後是「ello,world」。

所以這個全新的協議,你正在發明(我看到你提到你承認你在做,但你沒有解釋爲什麼這是一個好主意或應用程序的重要組成部分,而不是一個大的潛在錯誤的來源以及對時間的不良使用:)必須做一些稱爲「成幀」的事情,以便讓您實際解釋傳遞的字節序列。這就是爲什麼有像AMP這樣的協議。

要真正回答你的問題,outputStream write返回它實際上能夠緩衝用於發送的字節數。你必須經常檢查它的返回值,並重新嘗試寫任何字節它不是能夠發送,最好等待通知,有更多的緩衝空間之後。緩衝區空間在字節後變得可用,使用該空間通過網絡發送並由接收方確認。這需要時間,因爲網絡不是即時的。有關緩衝區空間的通知有多種形式,其中最古老和最普遍的是(但不一定是您所在環境中最好的),系統調用爲select(2)

0

除了Jean-Paul Calderone的回答(確保數據通過使用select或線程完全從obj-c端發送),對於協議部分,我建議使用帶長度前綴的字符串(AKA Netstring)用例。

這是implementation。每當收到某些東西時,您需要撥打NSBuffer.write然後NSBuffer.extract以獲取可用的字符串。