我目前正在为iPhone编写游戏,它通过TCP / IP与C ++服务器通信,以交换用户数据,朋友列表,声音文件等。在socket上读/写时,服务器和客户端使用相同的结构:
//Packet used for small stuff
typedef struct small_packet {
int msgtype:8;
int size:16;
int extra:16;
int following:24;
char data1[64];
char data2[64];
} packet;
//Packet used for files
typedef struct file_packet {
int msgtype:8; //For partial file packet this should be 0x02
int size:16;
int extra:16;
int following:24;
char data1[64];
char fileBuffer[1024];
} filePacket;
//Used for file headers
typedef struct filehead_packet {
int msgtype:8;
int size:16;
int extra:16;
int following:24;
char data1[64];
int fileid;
char rest[60];
} fileheadPacket;
在模拟器模式下,该应用程序可以正常工作,并通过互联网与服务器通信。然而,当在iPhone上运行时,它也不起作用。登录数据包使用小数据包(上部结构)。 msgtype为0x01,大小为sizeof(数据包),以下为0,extra为0,data1保存用户名,data2保存计算出的密码哈希值。服务器似乎获得0x01,因为它将传入消息视为登录请求。它也变大了。从data1和data2复制用户名和密码哈希时出现问题。
当cout在服务器上时,服务器似乎没有读取用户名的前三个字母。当我尝试使用say" username"登录时,服务器得到" rname&#34 ;,并且PWHash具有类似的偏移量(3 * sizeof(char))。这只发生在我在实际单元上运行应用程序时,而不是在模拟器中运行。
我承认我最近修改了结构的布局 - 到目前为止,额外字段只有8位,并且在后续字段后面还有一个额外的int:8字段。我已经在客户端和服务器上使用此信息更新了结构,并在两者上运行了clean + rebuild,所以我不明白为什么它会很重要。事实上,8 + 8 = 16,这是额外字段的新大小,因此data1和data2字段应该在内存中与旧结构相同的偏移量开始。
对此有任何帮助将不胜感激!我非常坚持这一点,并且真的很烦人,不知道什么是错的...它可能是我所知道的所有字母(iPhone是字性的,不是吗?),但如果是这样的话,我不知道服务器如何将0x01解释为0x01 ......哦。提前谢谢!
答案 0 :(得分:1)
我建议记录所有结构的sizeof - 包装可能是不同的mac / ios。如果是这样,clang可能有一些指令来完全像mac一样打包结构。此外,最好使用宏将所有数字转换为网络顺序(参见ntoh宏)。
更多的问题是你使用位域是非常不可移植的,理论上可能会随着编译器的更新而改变。我建议为发送器和接收器使用一组不同的“传输”结构,使用其中的uint64_t值作为标志:
typedef struct small_packet {
uint64_t flags;
char data1[64];
char data2[64];
} packet;
您可以编写非常简单的C代码,将“真实”结构映射到用于传输的结构。 K& R C警告不要在平台上使用位域(我只是查了一下: - ))。