iOS平台上的TCP方法

TCP Approach on the iOS platform

本文关键字:TCP 方法 平台 iOS      更新时间:2023-10-16

我目前正在开发一款需要与服务器通信的应用程序。我将传输两种不同大小的数据包,一个小数据包用于小数据(如sql请求),另一个大数据包用于文件(或文件片段,当文件超过1024字节时)。这些数据包看起来像这样:

小数据包:

typedef struct small_packet {
    int msgtype:8;
    int size:16;
    int following:24;
    char data1[64];
    char data2[64];
} packet;

大数据包:

typedef struct file_packet {
    int msgtype:8; //For partial file packet this should be 0x02
    int size:16;
    int following:24;
    char data1[64];
    char fileBuffer[1024];
} filePacket;

我已经使用select()在C++中编写了服务器的基本部分。服务器现在接受传入的连接,并在客户端请求时返回游戏列表

我对服务器通信的协议要求如下:

 *
 * Message types:
 * 0x01: Login message. Data1 is username, data2 is pw hash
 * 0x02: Login accepted/failed. Data1 is 1 for accept or 0 for not accepted
 * 0x03: New user. Data1 is username, data2 is pw hash
 * 0x04: New user accepted/failed. Data1 is 1 for accept and 0 for error
 * 0x05: Friend list request. Data1 is username and data2 should be 0
 * 0x06: Friend list header. Data1 is username and data2 should be 0
 * 0x07: Friend list packet. Data1 is username, data2 is 0
 * 0x08: Game list request. Data1 is username, data2 is 0
 * 0x09: Game list header. Data1 is username, data2 is game id
 * 0x0A: Game list packet. Following is gameID, data1 is randomness (0 or 1, first bit), data2 is players (divided by semicolon)
 * 0x0B: Friend add. Data1 is username, data2 is friend username
 * 0x0C: Random game add. Data1 is username, data2 is 0
 * 0x0D: Friend game add. Data1 is username, filebuffer holds friends' usernames, divided by semicolons
 * 0x10: File add. Data1 is username, data2 is game id
 * 0x11: File request. Data1 is username, data2 is game id
 * 0x12: File header. Data1 is turn number, data2 is game id
 * 0x13: File part. Data1 is 0, filebuffer is filepart
 *

现在,棘手的部分来了;我应该采取什么方法为iOS平台进行套接字编程?现在我有一个CFRead/WriteStreamRef&NSInput/OutputStream套接字通信器类,该类具有切换事件代码的流函数(如NSStreamEventHasBytesAvailable)。这似乎不太奏效。要么是我做错了什么,要么是请求响应太慢,要么是阻止读取。不管怎样,现在我只在请求游戏列表时得到0x09的回复。其余的要么从未被客户端接收到,要么因为程序已经过了读取时间而被丢弃(我不知道怎么回事)。

我正在考虑切换到出色的CocoaAsyncSocket API,但重写我的代码并不是很诱人。

有没有一种方法可以为iPhone编写一个简单的TCP客户端,它不阻塞,并接收可能转换为C风格结构的数据?我是否必须重新定义我的结构,甚至对数据使用其他东西?我喜欢例子,或者好的链接(相信我,我已经谷歌了!)。

非常感谢您的帮助!

您可以阅读关于使用CocoaAsyncSocket的简短介绍。

您可以通过以下方式轻松建立连接:

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

连接到您的服务器:

NSError *err = nil;
if (![socket connectToHost:@"yourserverip" onPort:80 error:&err]) // Asynchronous!
{
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(@"I goofed: %@", err);
}

现在将您的结构放入NSData:

NSData *myData = [NSData dataWithBytes:&myFilePacket length:sizeof(myFilePacket)];

并最终发送您的数据:

[socket writeData:myData withTimeout:-1 tag:1];

CocoaAsyncSocket还提供了许多有用的回调方法,如:

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag

或者对于传入的数据包,您可以将NSData强制转换回结构:

- (void)socket:(GCDAsyncSocket *)sender didReadData:(NSData *)data withTag:(long)tag
{
  filePacket packet;
  [data getBytes:&packet length:sizeof(packet)];
}

等等。。。看看头文件。。。

是的,就这么简单。