在我看来,如果流被另一个线程关闭而不管套接字连接的另一端是什么,那么任何NSInputStream对象都应弹出其read:方法。但在某些情况下,这似乎并非如此。似乎除非另一方在连接之前首先发送一次至少一次,否则read:方法将不响应流关闭。
打开连接的代码:
// Open the socket...
CFStreamCreatePairWithSocketToHost(NULL, Host, Port, &readStream, &writeStream);
// Create NSStream objects for our use...
inputStream = (NSInputStream *)readStream;
outputStream = (NSOutputStream *)writeStream;
// take ownership of the NSStream objects...
[inputStream retain];
[outputStream retain];
// open the streams....
[inputStream open];
[outputStream open];
关闭连接的代码:
// Close the streams...
[inputStream close];
[outputStream close];
// Release ownership...
[outputStream release];
[inputStream release];
// clear reference values...
outputStream = nil;
inputStream = nil;
在接收线程中:
-(uint8_t) GetByte
{
uint8_t c;
int N = [inputStream read:&c maxLength:1];
if ( N < 1 )
@throw [[TcpClientException alloc] init];
return c;
}
当我从主线程关闭流时,接收线程仍然在read方法中。最终它超时并崩溃。即使是崩溃也不会导致抛出任何类型的对象(我试图将代码包围起来以捕获任何东西(id)并且什么都没有)。
每次关闭流时,如何可靠地强制读取弹出?
此外:
我在ML和5.1 iPad模拟器上使用XCODE 4.4.1。
如果我只关闭inputStream并且不释放或设置为nil,那么也会出现问题。
答案 0 :(得分:0)
经过大量调查后,我在SO处遇到了另一个线程,暗示答案是,由于本地设备正在断开连接,因此通过read方法传递的连接(来自远程端点)不会发生任何事件。我们的想法是,由于本地设备负责断开连接,因此它会知道它不应该进入读取方法(没有任何东西可以读取)。这有点意外,因为当接收器线程已经在读取方法中时,用户可能正在断开连接。但是...... iOS的设计显然不是依赖于接收器线程,而是运行循环中的事件(这是另一个问题,但我不想进入这里)。具体来说,如果运行循环中的事件表明有可用数据,则输入read方法。因此,您永远不会输入读取和挂起等待第一个字节。这与我过去在Windows平台上完成的套接字编程非常不同。但到目前为止我所做的所有试验都表明这是问题所在。我现在有一个解决方案,它依赖于来自工作线程中的运行循环的流中的事件,以便网络流量不会干扰GUI(主)线程。