GCDAsyncSocket didReadData只被调用一次

时间:2015-03-26 20:19:32

标签: gcdasyncsocket

我正在尝试使用GCDAsyncSocket设置与iPhone客户端通信的Java服务器。出于某种原因,iPhone上的客户端代码没有读回所有数据。

我看到didReadData第一次被调用,但再也没有。理想情况下,我需要模仿HTTP协议的功能,它发送标头,然后发送有效负载。有效负载的大小将在标头中。但这不起作用,所以我进一步简化了我的代码,希望找到问题。下面是代码,下面是输出。

客户端:

- (BOOL) sendString:(NSString *) string
{
[asyncSocket writeData:[string dataUsingEncoding:NSUTF8StringEncoding]
withTimeout:-1 tag:TAG_PAYLOAD];

[asyncSocket readDataToLength:1 withTimeout:(-1) tag:TAG_HEADER];
}

- (void) socket:(GCDAsyncSocket *) sock didReadData:(NSData *)data   
withTag:(long)tag
{
NSString *str = [[NSString alloc] initWithData:data 
encoding:NSUTF8StringEncoding];
NSLog(@"Read data %@ with tag: %ld", str, tag);
if(tag == TAG_HEADER)
{
    //TODO - parse the header, get the fields
    [sock readDataToLength:3 withTimeout:-1 tag:TAG_PAYLOAD];
    //[sock readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 
    tag:TAG_PAYLOAD];
}
else
{
    NSLog(@"Payload... %@", str);
    NSLog(@"Tag: %ld", tag);
}
}

Java服务器:

BufferedReader   in = new BufferedReader(new     InputStreamReader(clientSocket.getInputStream()));
PrintWriter   out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

String clientCommand = in.readLine();
System.out.println("Client Says :" + clientCommand);
out.println("Andrew\r\nAUSTIN\r\n");
out.flush();

然而,在客户端,我唯一得到的回答是A.确切的输出是: 读取带有标签的数据A:10

我的问题是:

  1. 为什么再也没有调用didReadData方法?应该有更多的" Andrew \ r \ n \ nAustin"收回客户端。但它只是挂起。 readDataToData和readDataToLength似乎都没有得到完整的字符串。
  2. 我注意到GCDAsyncSocket.h中定义的CRLF不是\ r \ n而是十六进制值。这有关系吗?这就是为什么我尝试了readDataToLength方法,但仍然失败了。但我想知道这是否与跨平台有关。
  3. 感谢。

1 个答案:

答案 0 :(得分:2)

好的 - 所以我在拉出我留下的小头发后想出来了。

发生的事情是我在视图之外的一个单独的类中有上面的客户端代码。实际上我遇到的所有示例都在视图中处理了GCDAsyncSocket。它在那里很棒!我真的不想这样做,因为在每个视图中我都需要发送/读取数据并且不想复制我的工作。通过在这个辅助类的dealloc方法(称为SocketComm)中放置一条NSLog()行,我能够看到它在被触发之前被释放了。所以我需要改变我调用助手类的方式。我在viewController.h文件中声明SocketComm * sockComm是一个强属性,并在viewDidLoad()方法中分配它。这意味着它始终保持在范围内。当然,这意味着我需要手动解除分配并做一些其他管家工作。

就内存管理而言,我仍然不确定这是否是处理这种情况的最佳方法。因为现在我必须在每个viewDidLoad方法上分配它。看起来它应该比这更简单,但我们在这里。我仍然不知道为什么它从来没有第一次读取数据(我唯一的猜测是GCDAsyncSocket库或iphone软件在生成它的父级被解除分配并决定终止它时检测到死线程 - 但是这只是一个猜测,因为我刚刚开始目标-c)。

这也可以解释为什么有时它会起作用,有时它也不会起作用。好像它处于竞争状态。不确定我最初发布的上述代码是否完全导致竞争条件,但我会尝试的一些事情会起作用,然后下次失败。它从来没有读过多于第一次,只有大约一半的时间甚至会读到它。有时它甚至不会通过套接字发送数据!

总结(以及寻找答案的其他人):

  1. 始终检查您的内存管理。我不得不在SocketComm帮助程序类的dealloc()中放置一个NSLog来完全看到发生了什么,并且一旦我这样做,我就知道罪魁祸首是什么。
  2. 如果你得到奇怪的结果,有时它有效,有时它不会,检查你的内存管理。对我来说,有时它会做第一次阅读,有时它不会。这让我相信这个帖子已经被终止了。
  3. 如果我找到更好的方法,我会回来更新这个答案。
  4. 内存管理。让我再说一遍:记忆管理。