简体   繁体   English

NSOutputStream或扭曲的反应堆合并TCP数据包数据

[英]NSOutputStream or twisted reactor merging TCP packet data

I'm working on some networking code for an iPhone application that interfaces with a Python Twisted backend. 我正在为与Python Twisted后端接口的iPhone应用程序编写一些网络代码。 I've been running into a problem recently where it appears as though either my NSOutputStream is doubling up the payload on send OR twisted is doubling up the payload on receive. 我最近遇到了一个问题,好像我的NSOutputStream在发送时将有效载荷加倍,或者在扭曲时正在接收时将有效载荷加倍。

I'm using the "Apple Recommended" style of TCP sockets, EG non-polling. 我正在使用“ Apple推荐”样式的TCP套接字,例如EG非轮询。

The process is as follows: 流程如下:
CLIENT 客户
- NSStreamEventHasSpaceAvailable: send a packet of X bytes of data -NSStreamEventHasSpaceAvailable:发送一个X字节数据包
- NSStreamEventHasSpaceAvailable: send another packet of Y bytes of data -NSStreamEventHasSpaceAvailable:发送另一个Y字节数据包
SERVER 服务器
- Twisted receives packet of size (X + Y) bytes -Twisted接收大小为(X + Y)字节的数据包

I'm making sure I explicitly don't send data if the status of the outputStream is "NSStreamStatusWriting". 我确保如果outputStream的状态为“ NSStreamStatusWriting”,则明确发送数据。 Also ensuring that data is not allowed to be sent from the client if NSStreamEventHasSpaceAvailable has not been thrown. 此外,如果未抛出NSStreamEventHasSpaceAvailable,请确保不允许从客户端发送数据。

Any ideas as to what may be causing this double-up/merger of the payload? 关于什么可能导致有效载荷的这种双重/合并的任何想法? The Twisted code is fairly straight-forward, using the standard dataReceived in my Protocol: 使用我的协议中收到的标准数据,Twisted代码非常简单明了:

def dataRecieved(self, data):
        # do logic in order to decide how to handle data
        # ...
        # print of len(data) here reveals merged packet size

iOS code is fairly standard as well: iOS代码也相当标准:

if (eventCode == NSStreamEventHasSpaceAvailable)
    {
        [outputStream write:[packet getData] maxLength:[packet getPacketSize]];
    }
    // [packet getData] simply returns a standard UInt8 array. 
    // [packet getPacketSize] returns the size of that array.

When the above iOS code is called twice in a row (eg, sending two packets one after another), the twisted code reports the merged data size. 当上述iOS代码连续两次被调用(例如,一个接一个地发送两个数据包)时,扭曲的代码将报告合并的数据大小。

Thanks in advance for any advice or suggestions. 在此先感谢您的任何意见或建议。

I agree -- I shouldn't necessarily expect the buffer boundaries to match up, but I suppose it's a matter of predictable behavior. 我同意-我不必一定期望缓冲区边界匹配,但是我认为这是可预见的行为。

There is no predictable behavior in TCP based communications; 在基于TCP的通信中没有可预测的行为。 there may be any number of routers, NAT boundaries, goofy proxies or whatever in between you and the remote host that dictate behavior that appears unexpected. 可能有许多路由器,NAT边界,愚蠢的代理或您与远程主机之间的任何其他因素决定了行为似乎是意外的。

Heck, there might even be carrier pigeons carrying your packets byte by byte . 哎呀,甚至可能还有运鸽来逐字节地携带您的包裹

Real world, though, the behavior is generally fairly predictable. 但是,在现实世界中,行为通常是可以预测的。 But not always, never 100% of the time, and always with the potential of some customer somewhere with clogged tubes. 但并非总是如此,从来没有100%的时间,并且总是有某些客户的潜力在管堵塞的地方。

With TCP you are, at least, guaranteed that generally packets will be received in the order they are sent unless there is an error. 使用TCP,至少可以保证,除非出现错误,否则通常将按发送顺序接收数据包。 Assuming, again, that all points between are either implemented correctly or non-malicious (that latter bit means that you have to assume that sometimes data will be corrupted). 再次假设两者之间的所有点都正确实现或非恶意实现(后一点意味着您必须假设有时数据将被破坏)。

Even that guarantee doesn't mean much; 即使那个保证也没有多大意义。 you may receive the first 8 of 10 packets... or you might receive all of the in-bound data only to find the out-bound connection is dead when you go to respond.... 您可能会收到10个数据包中的前8个...或者您可能只收到所有入站数据,以发现去响应时出站连接已死。

Bottom line; 底线; your buffering algorithm on both sides must assume that the buffer may be filled in random bursts that completely mismatch the size of data stuck in the other side in the first place. 双方的缓冲算法都必须假设缓冲区可能填充了随机突发,这些突发完全与最初放在另一侧的数据大小不匹配。 While not strictly required, your app will be best served by defending against random connection failures; 尽管不是严格要求,但可以防止随机连接失败,从而为您的应用提供最佳服务; against truncated buffers, randomly broken connections and data corruption. 防止截断的缓冲区,随机断开的连接和数据损坏。

Early byte-length fields & checksums are your friend. 早期的字节长度字段和校验和是您的朋友。 Assumptions are you !hjfdahjdas8y! 假设是您!hjfdahjdas8y! $(& ($@#&^@#)^&! @#& _[CONNECTION LOST] $(& ($ @#&^ @#)^&! @#& __ [连接丢失]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM