我正在尝试在我的iOS游戏中实现远程资源加载,仅用于开发目的。所有艺术家都使用PC,我们只有一台Mac(我用它来编码),所以当他们做出改变时,他们需要停止工作只是为了在设备中看到它们(他们可以看到PC中的变化,但最后他们必须在设备上进行检查)。这就是我想尝试这个的原因。
我已经成功实现了服务器和客户端(使用TCP协议并以64KB的块发送文件),但它只适用于iPhone模拟器和PC(Mac使用与iPhone相同的WiFi连接)。我开始在两个平台上使用相同的代码进行连接(使用BSD套接字),但是在尝试了我脑海中的所有内容以便在iPhone上修复它之后,我使用CFStream在iPhone中实现了连接部分,因为我读到了使用BSD的地方套接字无法在网络上切换。尽管结果有点好(负载越来越远),但也失败了。
在我发送数据的方法中,我知道操作系统不必全部发送,所以我必须保持循环,直到我的所有数据都被发送。接收数据也一样。所以我认为这不是问题所在。
当我说所有这一切都失败时,我的意思是iPhone永远被锁定在'recv'中,有时它甚至连接到服务器(使用'connect'或'CFStreamCreatePairWithSocketToHost')。向聚会添加更多内容,当它在'connect'上被锁定时,如果我在'connect'调用之后放置一个断点,调试器会停止我的程序并且我可以从那里继续(虽然程序被锁定在一些随机的'recv'中')。
我不是网络编程方面的专家,所以我不会放弃我不理解TCP协议的“可靠”部分的选项,也许我丢失了一些数据包,这就是为什么iPhone被锁定在'recv'中(但这个理论并没有解释为什么'connect'有时会失败。)
顺便说一下,我在Windows 7 64位上使用WinSock 2.2,在iPod 4上使用iOS 4.2。
很抱歉写了这么长的帖子。我没有发布任何代码,因为我认为它太长了,但如果你认为有必要,请告诉我,我会。
非常感谢, 卡洛斯
编辑:我认为重要的是说我在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处理它)。
服务器部分是一个典型的侦听器套接字,其中包含阻塞“接受”的线程。我没有放这个代码,因为我不想膨胀帖子,我认为这部分工作正常。
编辑3:我创建了一个Ad-Hoc网络并将我的iPod直接连接到我的Windows 7 PC,它运行得很好。这对我来说是个好消息,但我仍然担心,因为我不想依赖于创建Ad-Hoc网络。这个问题可以在路由器中吗?我在这个问题上很丢失。