iOS平台上的TCP方法
TCP Approach on the iOS platform
我目前正在开发一款需要与服务器通信的应用程序。我将传输两种不同大小的数据包,一个小数据包用于小数据(如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)];
}
等等。。。看看头文件。。。
是的,就这么简单。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 是否有一种标准化的方法通过TCP/IP网络发送JPG图像
- 通过 TCP 发送多个字符数组的最快方法
- 处理 tcp/udp 接收的最佳方法
- 破坏TCP连接的好方法
- 网络tcp套接字应用程序重试方法
- iOS平台上的TCP方法
- 通过 tcp 中继目录树的最有效方法是什么?C++
- 向我的 TCP 客户端/服务器应用添加加密层的最直接方法是什么?
- 调用 boost::asio::tcp::socket 方法后async_read处理程序在服务器中返回错误
- 有没有更好的方法在C++中使用异步TCP套接字,而不是轮询或选择
- 实现TCP应用程序内置shell的简单方法
- 基于Cuda推力的TCP流分组方法