【发布时间】:2013-12-01 01:13:20
【问题描述】:
我目前正在为 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(packet),following 为 0,extra 为 0,data1 保存用户名,data2 保存计算得到的密码哈希值。服务器似乎获得了 0x01,因为它将传入消息视为登录请求。它也得到大小。从data1和data2复制用户名和密码哈希时出现问题。
在服务器上进行计算时,似乎服务器未读取用户名的前三个字母。当我尝试使用“用户名”登录时,服务器获取“rname”,并且 PWHash 具有类似的偏移量(3*sizeof(char))。这只发生在我在实际单元上运行应用程序时,而不是在模拟器中。
我承认我最近修改了结构的布局——到目前为止,额外字段只有 8 位,并且在后续字段之后我还有一个额外的 int:8 字段。我已经在客户端和服务器上使用此信息更新了结构,并在两者上运行了 clean+rebuild,所以我不明白它为什么重要。事实上,8+8=16,这是额外字段的新大小,因此 data1 和 data2 字段应该在内存中的相同偏移处开始,就像它们过去使用旧结构一样。
对此的任何帮助将不胜感激!我非常坚持这一点,完全不知道出了什么问题真的很烦人......这可能是我所知道的字节顺序(iPhone是字节性,不是吗?),但如果是这样的话,我不知道怎么做服务器将 0x01 解释为 0x01 ......哦,好吧。提前致谢!
【问题讨论】:
-
据我所知,服务器是一个实际的远程服务器,对吧?因为如果是
localhost,你需要使用本地主机的IP,而不是在你的应用中使用localhost。 -
只是一个想法:会不会是 utf8 的问题?我的意思是你的用户名实际上是“用户名”还是用挪威语写的?
-
服务器是远程的,我将完整的 ipv4 地址硬编码到我的应用程序中。 @gWiz:我的用户名仅由英文字母表中的纯字母组成。事实上,客户端只接受 [a...z] 中的用户名。
-
我建议为所有结构记录 sizeof - 包装可能是不同的 mac/ios。如果是这样,clang 可能有一些指令可以像 mac 一样打包结构。此外,使用宏将所有数字转换为网络顺序也是一种很好的做法(请参阅 ntoh 宏)。
-
谢谢@DavidH!我今晚回去工作时会试试这个。在这种情况下,我跳过了 htons/ntohs,因为两台机器都以网络字节序工作,但我同意使用它们是一种好习惯,我稍后会将它添加到我的程序中。不同的包装是我没有想到的——谢谢,我回去工作时看看是不是这样:)
标签: c++ ios iphone objective-c tcp