Read()阻塞问题

时间:2009-07-27 18:47:15

标签: c# tcpclient

我正在用C#开发一个服务器应用程序。客户端可以连接到服务器并发出各种请求。目前,当客户端连接时,我会生成一个新线程来处理请求。我正在使用TCPClient类来处理客户端连接。我的服务器工作原理如下:

  1. 客户端通过请求连接到服务器
  2. 服务器处理请求
  3. 服务器等待查看客户是否还有其他请求
  4. 如果客户端在某个超时期限内未发出其他请求,则服务器将终止连接
  5. 我的问题如下:

    当我从TCPClient类中获取的NetworkStream对象中读取时,如果没有可用数据,则NetworkStream Read()方法不会阻止。当服务器到达步骤#3时,我想在NetworkStream上设置一些超时,如果客户端在该持续时间内没有再发出任何请求,则服务器应该在抛出超时异常时终止连接。当我的服务器到达第3步时,NetworkStream Read()方法不会阻塞,无论我设置它的ReadTimeout属性是什么。任何人都可以帮助我,或建议一个更好的方法来做我想做的事。

    由于

6 个答案:

答案 0 :(得分:2)

如果没有要读取的数据,

NetworkStream.Read和ReadByte应该阻塞直到超时。我认为这个调用更有可能是读取一些东西,可能是一堆零。仔细检查客户端发送的数据。

答案 1 :(得分:0)

您应该从使用Read()到BeginRead()方法毕业并研究并行处理。网络编程不适合胆小的人。

基本上,您不希望为数据创建循环轮询。

while(!timedout && !stream.DataAvailable) sleep(0); // This is bad.
if(steam.DataAvailable) steam.Read();

相反,做这样的事情会更有意义。创建一个重置事件,调用BeginRead(),并在回调上释放重置事件。如下所示:

void clientThread()
{
   stream.BeginRead(myCallback);
   resetEvent.WaitOne(timeout)
}
void myCallback
{
   resetEvent.Set();
}

答案 2 :(得分:0)

将网络流包裹在BufferedStream中。 BufferedStream.Read将阻塞,直到至少有1个字节可用。

答案 3 :(得分:0)

这是你要找的吗?

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.receivetimeout.aspx

看起来你使用GetStream()从TcpClient获取NetworkStream,然后在其上调用Read()方法。

答案 4 :(得分:0)

在没有可用数据时显式强制NetworkStream阻止:

TcpClient clientConnection = new TcpClient();

if(clientConnection.Available > 0)
{ 
  //You want to continue execution even though there is no available data to be read from the server then:
  clientConnection.Client.Blocking = false;
}

答案 5 :(得分:-1)

你需要自己处理“超时”,因为NetworkStream.Read()没有提供这样做的方法。

您可能希望在客户端线程中执行的操作是使用NetworkStream.DataAvailable和/或NetworkStream.CanRead的某些组合以及阻塞/超时机制(例如使用具有超时的WaitHandle.WaitOne调用)为客户提供时间来提供数据。如果在指定时间后没有任何内容,请关闭连接,然后退出。