我正在尝试使用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
我的问题是:
感谢。
答案 0 :(得分:2)
好的 - 所以我在拉出我留下的小头发后想出来了。
发生的事情是我在视图之外的一个单独的类中有上面的客户端代码。实际上我遇到的所有示例都在视图中处理了GCDAsyncSocket。它在那里很棒!我真的不想这样做,因为在每个视图中我都需要发送/读取数据并且不想复制我的工作。通过在这个辅助类的dealloc方法(称为SocketComm)中放置一条NSLog()行,我能够看到它在被触发之前被释放了。所以我需要改变我调用助手类的方式。我在viewController.h文件中声明SocketComm * sockComm是一个强属性,并在viewDidLoad()方法中分配它。这意味着它始终保持在范围内。当然,这意味着我需要手动解除分配并做一些其他管家工作。
就内存管理而言,我仍然不确定这是否是处理这种情况的最佳方法。因为现在我必须在每个viewDidLoad方法上分配它。看起来它应该比这更简单,但我们在这里。我仍然不知道为什么它从来没有第一次读取数据(我唯一的猜测是GCDAsyncSocket库或iphone软件在生成它的父级被解除分配并决定终止它时检测到死线程 - 但是这只是一个猜测,因为我刚刚开始目标-c)。
这也可以解释为什么有时它会起作用,有时它也不会起作用。好像它处于竞争状态。不确定我最初发布的上述代码是否完全导致竞争条件,但我会尝试的一些事情会起作用,然后下次失败。它从来没有读过多于第一次,只有大约一半的时间甚至会读到它。有时它甚至不会通过套接字发送数据!
总结(以及寻找答案的其他人):