如何使用 GCDASyncSocket 时分隔数据的数据包
1个回答
推荐于2016-06-12 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
向TA提问 私信TA
知道合伙人数码行家
采纳数:117538
获赞数:517195
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。
向TA提问 私信TA
关注
展开全部
解决方法 1:
你被误解的标记的作用吧。GCDAsyncSocket是 (顾名思义) asynchrone套接字。该标记可以帮助您以匹配与接收订单接收到的数据和发送成功者与发送订单,和
例如,如果您想要发送的数据,则使用 writeData:messageA withTimeout:-1 tag: tagA (或类似的东西) 给你的套接字的顺序发送somewhen 在不久的将来。它不一定现在会。然后你就可以立即给下一个订单发送另一条消息,说messageB 与标记 tagB 。要知道, messageA 真的发送,你能通过通知 socket:aSocket didWriteDataWithTag:aTag 。在这里, aTag 的值 tagA 如果 messageA 发送的和的值 tagB 如果 messageB 被送。标记不会发送消息 ;它只是帮助您确定您的订单。
它是在接收方的相同的事情。您给的顺序接收 (somewhen) 的一些数据和将标记分配给这个非常的顺序。一旦你做了接收数据、 通知 (通过 socket:didReadData:withTag: ) 显示你要让你知道的标记顺序取得成功。
您可能使用标记的一些语义信息并把它放在您的消息。但即使在当时,在该通知中的标记的标记中收到的订单,但从来没有发送订单之一。如果您想要使用你把放在接收方的消息中的标记,您必须接收 (至少部分的) 消息第一次和解析它。
来到您的问题的核心: 你有基本上两种可能性,知道,哪些类型的数据到达:
知道发送的数据的顺序和接收它非常相同的顺序。
使用标识的数据类型的邮件头。接收只有头和接收并解析您的邮件的遗骸在头数据的依赖性。
编辑
这里是一个示例的第二个办法。假设你可以发送数量的对象的类 A、 B,等等。您的数据的类型和大小,可以包括您的标头:
typedef struct {
NSUInteger type_id;
NSUInteger size;
} header_t;
#define typeIdA 1
#define typeIdB 2
// ...
一旦您要发送的对象 obj 与 objKey:
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:obj forKey: objKey];
header_t head;
if ([obj class] == [A class]) {
head.type_id = typeIdA;
} else if ([obj class] == [B class]) {
head.type_id = typeIdB;
} else ...
// ....
header.size = data.lengh;
NSData* headData = [NSData dataWithBytes: &header length: sizeof(header)];
dataWithBytes:length:
header = NSData.length;
[asyncSocket writeData:headData withTimeout:-1 tag:headTag];
[asyncSocket writeData:data withTimeout:-1 tag:dataTag];
如果你想,你可以得到通知上成功发送或错误,但在这里跳过这。在接收方,你第一次期待一个标头:
[receiveSocket readDataToLength:sizeof(header_t) withTimeout:-1 tag:rcvHdrTag];
// rcvHdrTag must not match one of the typeIdX tags
在你 socket:didReadData:withTag: 你要区分开来,如果你的标题或遗骸 (接收的仍然这里开始!)
- (void)socket:(GCDAsyncSocket *)aSocket didReadData:(NSData *)data withTag:(long)tag {
header_t head;
id obj;
id key;
switch (tag) {
case rcvHdrTag:
[data getBytes:&head length:sizeof(header)];
// now you know what to receive
[aSocket readDataToLength:header.size withTimeout:-1 tag:header.type];
return;
break; // I know, redundancy :-)
case typeIdA:
objKey = objKeyA; // whatever it is...
break;
case typeIdB:
objKey = objKeyB;
// ....
}
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
obj = [unarchiver decodeObjectForKey:objKey];
// store your object ...
}
这不是最优雅的例子,和它忽略对象树和对象间的依赖关系,在档案里,但你应该知道。
你被误解的标记的作用吧。GCDAsyncSocket是 (顾名思义) asynchrone套接字。该标记可以帮助您以匹配与接收订单接收到的数据和发送成功者与发送订单,和
例如,如果您想要发送的数据,则使用 writeData:messageA withTimeout:-1 tag: tagA (或类似的东西) 给你的套接字的顺序发送somewhen 在不久的将来。它不一定现在会。然后你就可以立即给下一个订单发送另一条消息,说messageB 与标记 tagB 。要知道, messageA 真的发送,你能通过通知 socket:aSocket didWriteDataWithTag:aTag 。在这里, aTag 的值 tagA 如果 messageA 发送的和的值 tagB 如果 messageB 被送。标记不会发送消息 ;它只是帮助您确定您的订单。
它是在接收方的相同的事情。您给的顺序接收 (somewhen) 的一些数据和将标记分配给这个非常的顺序。一旦你做了接收数据、 通知 (通过 socket:didReadData:withTag: ) 显示你要让你知道的标记顺序取得成功。
您可能使用标记的一些语义信息并把它放在您的消息。但即使在当时,在该通知中的标记的标记中收到的订单,但从来没有发送订单之一。如果您想要使用你把放在接收方的消息中的标记,您必须接收 (至少部分的) 消息第一次和解析它。
来到您的问题的核心: 你有基本上两种可能性,知道,哪些类型的数据到达:
知道发送的数据的顺序和接收它非常相同的顺序。
使用标识的数据类型的邮件头。接收只有头和接收并解析您的邮件的遗骸在头数据的依赖性。
编辑
这里是一个示例的第二个办法。假设你可以发送数量的对象的类 A、 B,等等。您的数据的类型和大小,可以包括您的标头:
typedef struct {
NSUInteger type_id;
NSUInteger size;
} header_t;
#define typeIdA 1
#define typeIdB 2
// ...
一旦您要发送的对象 obj 与 objKey:
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:obj forKey: objKey];
header_t head;
if ([obj class] == [A class]) {
head.type_id = typeIdA;
} else if ([obj class] == [B class]) {
head.type_id = typeIdB;
} else ...
// ....
header.size = data.lengh;
NSData* headData = [NSData dataWithBytes: &header length: sizeof(header)];
dataWithBytes:length:
header = NSData.length;
[asyncSocket writeData:headData withTimeout:-1 tag:headTag];
[asyncSocket writeData:data withTimeout:-1 tag:dataTag];
如果你想,你可以得到通知上成功发送或错误,但在这里跳过这。在接收方,你第一次期待一个标头:
[receiveSocket readDataToLength:sizeof(header_t) withTimeout:-1 tag:rcvHdrTag];
// rcvHdrTag must not match one of the typeIdX tags
在你 socket:didReadData:withTag: 你要区分开来,如果你的标题或遗骸 (接收的仍然这里开始!)
- (void)socket:(GCDAsyncSocket *)aSocket didReadData:(NSData *)data withTag:(long)tag {
header_t head;
id obj;
id key;
switch (tag) {
case rcvHdrTag:
[data getBytes:&head length:sizeof(header)];
// now you know what to receive
[aSocket readDataToLength:header.size withTimeout:-1 tag:header.type];
return;
break; // I know, redundancy :-)
case typeIdA:
objKey = objKeyA; // whatever it is...
break;
case typeIdB:
objKey = objKeyB;
// ....
}
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
obj = [unarchiver decodeObjectForKey:objKey];
// store your object ...
}
这不是最优雅的例子,和它忽略对象树和对象间的依赖关系,在档案里,但你应该知道。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询