Я пытаюсь реализовать удаленную загрузку ресурсов в моей игре для iOS, только для целей разработки. Все художники работают с ПК, и у нас есть только один Mac (который я использую для кодирования), поэтому, когда они вносят изменения, им нужно остановить мою работу, просто чтобы увидеть их на устройстве (они могут видеть изменения на ПК, но, наконец, они должны быть проверены на устройстве). Вот почему я хочу попробовать это.
Я успешно реализовал сервер и клиент (используя протокол TCP и отправляю файлы кусками по 64 КБ), но он работает только на iPhone Simulator и ПК (Mac использует то же соединение WiFi, что и iPhone). Я начал использовать один и тот же код для подключения на обеих платформах (используя сокеты BSD), но после того, как все, что у меня было в голове, попыталось исправить это на iPhone, я реализовал часть соединения в iPhone с помощью CFStream, потому что где-то читал, что с помощью BSD сокеты не включаются в сеть. Несмотря на то, что результат был немного лучше (нагрузка пошла дальше), он тоже потерпел неудачу.
В моем методе отправки данных я знаю, что ОС не должна отправлять все это, поэтому я должен держать цикл, пока все мои данные не будут отправлены. То же самое для получения данных. Так что я не думаю, что это проблема.
Когда я говорю, что все это терпит неудачу, я имею в виду, что iPhone навсегда заблокирован внутри «recv», а иногда он даже не подключается к серверу (используя «connect» или «CFStreamCreatePairWithSocketToHost»). Добавляя больше к стороне, когда она блокируется на 'connect', если я ставлю точку останова после вызова 'connect', отладчик останавливает мою программу там, и я могу продолжить с нее (хотя программа блокируется в некотором случайном 'recv ').
Я не эксперт по сетевому программированию, поэтому я не отказываюсь от варианта, что я не понимаю «надежную» часть протокола TCP, и, возможно, я потеряю некоторый пакет, и это является причиной того, что iPhone блокируется внутри «recv» (но эта теория не объясняет, почему иногда «connect» не срабатывает).
Кстати, я использую WinSock 2.2 на 64-битной Windows 7 и iOS 4.2 на iPod 4.
Извините, что написал такой длинный пост. Я не публикую ни одного кода, потому что я упал, это будет слишком долго, но если вы считаете это необходимым, пожалуйста, сообщите мне, и я сделаю это.
Большое спасибо,
Carlos
РЕДАКТИРОВАТЬ: я думаю, важно сказать, что я не использую несколько потоков для этой цели в iPhone, и сокеты блокируют (ну, по крайней мере, я явно не помещаю их в неблокирующее состояние. Мое понимание это то, что они блокируют по умолчанию)
РЕДАКТИРОВАТЬ 2: Хорошо, давайте добавим код =)
bool CTCPStream::connect( const CNetIP &ipDestination, uint32_t port ) {
CFStringRef host = CFStringCreateWithCString( kCFAllocatorDefault, ipDestination.toString( ).c_str( ), kCFStringEncodingASCII );//CFSTR( "192.168.1.99" );
UInt32 p = port;
CFStreamCreatePairWithSocketToHost( kCFAllocatorDefault, host, p, &_readStream, &_writeStream );
if( !_readStream || !_writeStream ) {
close( );
return false;
}
if( !CFWriteStreamOpen( _writeStream ) || !CFReadStreamOpen( _readStream ) ) {
close( );
return false;
}
CFReadStreamSetProperty( _readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue );
CFWriteStreamSetProperty( _writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue );
return true;
}
boost::optional< uint32_t > CTCPStream::sendBytes( const void *ptr, uint32_t size ) const {
const UInt8 *source = reinterpret_cast< const UInt8* >( ptr );
uint32_t bytesSent = 0;
while( size ) {
int bytes = CFWriteStreamWrite( _writeStream, &source[ bytesSent ], size );
if( bytes == -1 )
return boost::optional< uint32_t >( );
size -= bytes;
bytesSent += bytes;
}
return bytesSent;
}
boost::optional< uint32_t > CTCPStream::recvBytes( void *ptr, uint32_t size ) const {
GASSERT( isConnected( ) );
GASSERT( size );
UInt8 *target = reinterpret_cast< UInt8* >( ptr );
uint32_t bytesRead = 0;
while( size ) {
int bytes = CFReadStreamRead( _readStream, &target[ bytesRead ], size );
if( bytes == -1 )
return boost::optional< uint32_t >( );
size -= bytes;
bytesRead += bytes;
}
return bytesRead;
}
И этого не намного больше. В начале приложения для iPhone я выполняю «соединение» (которое иногда завершается неудачно, как было сказано ранее) и начинаю выполнять send и recv без подтверждения (насколько я понимаю, TCP это обрабатывает).
Серверная часть представляет собой типичный сокет прослушивателя с потоком для блокировки 'accept'. Я не помещаю этот код, потому что я не хочу раздувать пост, и я думаю, что эта часть работает нормально.
РЕДАКТИРОВАТЬ 3: Я создал сеть Ad-Hoc и напрямую подключил мой iPod к ПК с Windows 7, и он работал отлично. Это хорошая новость для меня, но я все еще волнуюсь, потому что я не хотел бы полагаться на необходимость создания специальной сети. Может проблема в роутере? Я довольно потерян в этой теме.