В настоящее время я пишу игру для iPhone, которая связывается с сервером C++ через TCP/IP для обмена пользовательскими данными, списками друзей, звуковыми файлами и т.д. Сервер и клиент используют одни и те же структуры при чтении/записи в сокете:
//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'ing на сервере, кажется, что первые три буквы имени пользователя не прочитаны сервером. Когда я пытаюсь войти с именем "username", сервер получает "rname", а PWHash имеет аналогичное смещение (3 * sizeof (char)). Это происходит только при запуске приложения на самом устройстве, а не в симуляторе.
Я признаю, что недавно я изменил компоновку структур - до сих пор в дополнительном поле было всего 8 бит, и после следующего поля у меня было дополнительное поле int: 8. Я обновил структуры с этой информацией как на клиенте, так и на сервере, и запустил чистую + перестройку для обоих, поэтому я не понимаю, почему это имеет значение. И по сути, 8 + 8 = 16, который является новым размером дополнительного поля, поэтому поля data1 и data2 должны начинаться с того же смещения в памяти, что и для старых структур.
Любая помощь с этим будет принята с благодарностью! Я очень зациклен на этом, и это действительно раздражает, не зная, что вообще не так... Это может быть консенсус для всего, что я знаю (iPhone - байотный, не так ли?), Но если это случай, я понятия не имею, как сервер интерпретирует 0x01 как 0x01... ну хорошо. Заранее спасибо!
Я предлагаю регистрировать 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 предупреждает против использования битовых полей на разных платформах (я просто посмотрел вверх :-)).
localhost
, вам нужно использоватьIP
localhost, а неlocalhost
в вашем приложении.