c++ - iOS 平台上的 TCP 方法

标签 c++ ios objective-c sockets tcp

我目前正在开发一个需要与服务器通信的应用程序。我要传输两种不同大小的数据包,一个小数据包用于小数据(例如 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++ 编写了服务器的基本部分。服务器现在接受传入连接,并在客户端请求时返回游戏列表。我已经用一个用 C 编写的简单客户端对此进行了测试。

我对服务器通信的协议(protocol)要求如下所示:

 *
 * 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 套接字通信器类,它有一个流功能,可以切换 eventCodes(例如 NSStreamEventHasBytesAvailable)。这似乎不太奏效。要么是我做错了什么,要么是请求响应太慢或阻塞读取时遇到问题。无论哪种方式,现在我在请求游戏列表时只收到 0x09 回复。其余的要么从未被客户端接收到,要么因为程序已经超过读取而被丢弃(我不知道如何)。

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

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

非常感谢任何帮助!

最佳答案

你可能会读到 this short intro关于使用 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)];
}

等等... 查看头文件...

是的,就是这么简单。

关于c++ - iOS 平台上的 TCP 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20070947/

相关文章:

c++ - 递归算法的实现

ios - 在自定义 UITextField 上关闭键盘

ios - 使用 libgdx (roboVM) 创建 iOS 库或框架

iphone - 在 iphone 中将此 Html 文本转换为简单文本

c++ - 如何确保作为模板参数传递的函数类型不修改参数?

c++ - 在 C++ 容器中一起使用所有子类的设计

ios - 由于 'private' 级保护 - swift,无法访问“restoreProgress”

ios - 与 iPhone SDK 中的 session 相比,Flurry 日志事件更新相当晚

ios - 调整 MKMapView 大小后的 zoomScale 不等于绘制 MKOverlay 时的 zoomScale

c++ - 这个 pow() 函数在 while 循环 C++ 中发生了什么?