请教,郁闷死了AsyncSocket接收大的数据时就接收的不完整

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教,郁闷死了AsyncSocket接收大的数据时就接收的不完整相关的知识,希望对你有一定的参考价值。

参考技术A 如果我没猜错的话,问题出在你的C#服务端!

看一下你代码中的这条语句
[self.outSocket readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0];

参数[AsyncSocket CRLFData]表示读取至"\r\n"
查查你的C#服务端在返回数据时结尾有没有追加"\r\n",没有的话加上,否则didReadData永远不会执行。

另,使用开源三方库前,有文档的话好好看一下,没有的话就看一下头文件,大部分规范的开源代码在头文件中都会加入说明,这个问题头文件里说的很清楚

/**
* Reads bytes until (and including) the passed "data" parameter, which acts as a separator.
*
* If the timeout value is negative, the read operation will not use a timeout.
*

* If you pass nil or zero-length data as the "data" parameter,

* the method will do nothing, and the delegate will not be called.

*

* To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.

* Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for

* a character, the read will prematurely end.
**/
- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
-本回答被提问者采纳
参考技术B 用readDataToLength 通过数据报文长度来确认你要取的数据
报头里面记录报文格式信息 包含数据报文大小
再读报体
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
报体大小如果刚好同报头记录的数据大小一样
继续读取下一个报头
否则
修正偏移
if (self.dataLen == self.dataBody.length)

[self readData:HaderSize withTag:tagReadHeader];//read for next package.

else
NSInteger fixLen = dataLen - data.length;
if (fixLen>0)
dataLen = fixLen;
[self readData:fixLen withTag:tagReadBody];

else
[self disconnection];//for renconnection.

GCDAsyncSocket - 不接收数据 - AsyncSocket 工作正常

【中文标题】GCDAsyncSocket - 不接收数据 - AsyncSocket 工作正常【英文标题】:GCDAsyncSocket - not receiving data - AsyncSocket works ok 【发布时间】:2011-07-01 13:17:43 【问题描述】:

我让 iPhone 客户端使用 GCDAsyncSocket 连接到服务器。服务器在 Windows 服务器上运行 .Net。连接很好,发送数据也很好。

然后我告诉客户端在发送后直接进入接收...

[sock readDataToData:[GCDAsyncSocket LFData] withTimeout:15 tag:1]; 

我也有这个设置来接收:

- (void)onSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data 
withTag:(long)tag 

还有:

   - (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag 

如果我等待超时,则会调用超时方法。

如果我从服务器发送数据,则不会调用超时,所以我假设 客户看到了一些东西,但没有任何迹象表明 客户端。

我还加了:

- (void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength: (NSUInteger)partialLength tag:(long)tag 

希望我能看到部分数据包,但这不会被触发 任何一个。

正如我上面提到的,如果我发送超时不会触发 从服务器到客户端的东西。不过我本来以为 如果它没有收到终止符,它也会超时 特点。我也尝试阅读长度为 3,但没有 有所作为。

GCDAsyncSocket 是问题所在。 AsyncSocket 似乎工作正常。

也许它的初始化是错误的?

dispatch_queue_t mainQueue = dispatch_get_main_queue();

asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue]

任何想法我做错了什么?

我为此在护目镜代码上发了一个帖子,但没有任何活动,所以不确定我是否会得到答案。

理想情况下,如果有人有接收工作的示例代码,那就太好了!谢谢!

【问题讨论】:

【参考方案1】:

也许拼写有问题。 (所以这发生在我身上,我一直在寻找几个小时,直到我看到了细微的差别)

GCDAsyncSocket 将所有委托回调从 onSocket 重命名为 socket 以匹配 Apple 的命名风格。

在你上面的例子中你提到了

- (void)onSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 

重命名为

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 

这应该可以解决这个问题。

在我的代码中,我也遇到了另一个问题。 确保调用 GCDAsyncSocket 的对象在您连接时仍然存在。 GCDAsyncSockets 委托是对您的对象的弱引用。并且因为它是异步的,所以当套接字响应时,委托可以变为零(自动释放,或者实例是在已经离开的方法中创建的)。结果它似乎没有被调用,但是启动套接字的类已经从内存中释放了。如果您将 ARC 与 GCDAsyncSocket 一起使用,则会发生这种情况。

希望对你有帮助

【讨论】:

关于弱引用的信息帮助了我。我从来没有发现过。谢谢 一千个感谢!这让我望而却步。 GCDAsyncSockets 委托是一个弱引用让我迷路了!对于那些仍在苦苦挣扎的人,正如@JackPearse 已经说过的那样,如果didAccept 方法中的newSocket 离开该方法,则会被ARC 清理掉,ARC 是一个垃圾收集器。您必须将其分配给类的成员变量以确保 ARC 不会清理您的 newSocket。【参考方案2】:

您确定您的服务器正在发送仅以 LineFeed 而不是 CRLF 终止的数据吗?或者您从服务器发回的数据可能没有以任何方式终止? readDataToData 将一直等待,直到它在接收到的数据中遇到终止字符。

这是我用来连接的代码。我已经删除了我认为不必要的内容 - 希望我没有删除任何重要的内容。

初始化套接字

asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

连接

[asyncSocket connectToAddress:addr error:&err]

连接中

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port 
    connected = YES;

发送(无超时)

[asyncSocket writeData:dataData withTimeout:-1 tag:0];

请求读取数据

[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:30.0 tag:0];

数据已通过(我只是发送字符串)

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

【讨论】:

是的,它肯定发送正确。我尝试使用 telnet 连接到服务器,一切都很好。我还切换了 .h 和 .m 以使用没有 GDC 的旧版本,并且可以正常工作。 @Mark Worsnop 查看更新的答案 - 我已包含用于连接和发送/接收数据的代码。希望能有所帮助! 我更改为没有 GCD 的 AsyncSocket 类,它或多或少地工作。 NSData 似乎对你如何设置它很挑剔,但让它保持简单它确实有效。然后我改回 GCD 类,同样的问题。 我不知道还有什么建议。我遇到的唯一问题是 iOS5 的蓝牙问题,但这仍在 NDA 之下,所以我不能谈论这个。 这段代码对我有用……我只需要确保我发送的所有字符串都附有 \r\n。【参考方案3】:

我有同样的问题,准备放弃。我的问题是服务器端。在我的委托方法 onSocket:didAcceptNewSocket: 我在错误的套接字上调用读取。这解决了它。

-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket

    NSLog(@"Connection Socket connected to ipad at %@",[newSocket connectedHost]);
    _ipadSocket = newSocket;
    [_ipadSocket setDelegate:self];

    //***This code was the faulty line. I was calling listen on sock not newSocket
    [_ipadSocket readDataToData:[AsyncSocket CRLFData] withTimeout:10 tag:0];

【讨论】:

是的,我也被困住了。但是,从 AsyncSocket “RUNLOOP”示例中不清楚此语法是否正确。例如,newSocket 委托似乎是继承的。不过谢谢你指路! 谢谢,我也在 Sock 上调用 readData 而不是“newSocket”【参考方案4】:

我认为问题出在您发送的内容上。 如果内容在文件中的某处包含 LF,则读取将在读取 LF 时结束。 您应该在发送文件之前进行 base64 编码或读取到一个大小。

【讨论】:

【参考方案5】:

添加:

[sock readDataWithTimeout:-1 tag:0];

在 didConnectToHost 的末尾。

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port

    //Your Code

    [sock readDataWithTimeout:-1 tag:0];

【讨论】:

如果有人在 2021 年遇到同样的问题,这可能仍然对你有用,它肯定对我有用【参考方案6】:

我开发了几乎相同的代码,端服务器ios端客户端vb网。 从 vb.net 我使用方法 socket.sendfile 发送一个 147 kb 的文件,而在 ios 中使用 AsyncSocket 所以:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;


        [sock readDataToData:[AsyncSocket CRData] withTimeout:-1 tag:0]; 

        [dataFile appendData:data];

我在连接和开始发送/接收方面没有任何问题,但我唯一的问题是,如果我使用 CRData,我会收到 152 kb,如果我使用 LFData 分隔符,我会收到 143 kb。

答案是我发送文件时如何在vb net中添加分隔符?

【讨论】:

以上是关于请教,郁闷死了AsyncSocket接收大的数据时就接收的不完整的主要内容,如果未能解决你的问题,请参考以下文章

ios socket第三方框架 AsyncSocket使用简介,连接,心跳,断线,数据发送与接收

bash的问题,郁闷死我了

如何通过 iOS 中的套接字从服务器接收数据?

AsyncSocket:合并两个数据包而不是单独的两个数据包

iOS--(转)socket编程之Asyncsocket详解

AsyncSocket 委托方法调用不正确?