C++ iOS平台上的TCP方法

C++ iOS平台上的TCP方法,c++,ios,objective-c,sockets,tcp,C++,Ios,Objective C,Sockets,Tcp,我目前正在开发一个需要与服务器通信的应用程序。我将传输两种不同大小的数据包,一个用于小数据(如sql请求)的小数据包和一个用于文件(或文件片段,当文件超过1024字节时)的大数据包。这些数据包如下所示: * * 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

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

 *
 * 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
 *
小包:

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;
<>我用C++(Stual())在C++中编写了服务器的基本部分。服务器现在接受传入的连接,并在客户端请求时返回游戏列表。我已经用一个用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 socket communicator类,它有一个流函数,可以切换事件代码(比如nsStreamEventThasBytesAvailable)。这似乎不太管用。要么我做错了什么,要么我遇到了问题,要么我的请求被回答得太慢,要么我阻碍了阅读。无论哪种方式,现在我只在请求游戏列表时收到0x09回复。其余的要么从未被客户端接收到,要么因为程序已经超过了读数而被删除(我不知道怎么做)

我正在考虑切换到很棒的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)];
}
等等。。。 看看头文件


是的,就这么简单。

谢谢,我现在已经用AsyncSocket重写了我的servercomm的一部分。服务器似乎接受客户机,并根据请求返回数据包,但我的客户机不读取服务器发送的数据包。在我看来,似乎-(void)socket:(GCDAsyncSocket*)sender didReadData:(NSData*)data with tag:(long)tag委托函数从未被回调。奇怪。。。O好的,回到调试上来。再次感谢:)您可以将
GCDAsyncSocket*socket
声明为属性或实例变量。否则,它可能会在您的数据发送后被销毁。这似乎不起作用@chris。我仍然不知道为什么当didWrite和didConnect的委托函数工作时,它不启动某些委托函数。您可以将NSLog消息放入
-(void)socketDidDisconnect:(GCDAsyncSocket*)sock withError:(NSError*)err中回调方法,以查看套接字是否因任何原因断开连接。