C# Read() 阻塞问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1189917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Read() blocking problem
提问by
I'm developing a server application in C#. Clients can connect to the server and make various requests. Currently, when a client connects I spawn a new thread to handle the request(s). I'm using the TCPClient class to handle client connections. My server works as follows:
我正在用 C# 开发服务器应用程序。客户端可以连接到服务器并发出各种请求。目前,当客户端连接时,我会生成一个新线程来处理请求。我正在使用 TCPClient 类来处理客户端连接。我的服务器工作如下:
- Client connect to server with a request
- Server handles request
- Server waits to see if client has any more requests
- If client does not make another request within some timeout period, the server kills the connection
- 客户端通过请求连接到服务器
- 服务器处理请求
- 服务器等待查看客户端是否有更多请求
- 如果客户端在某个超时时间内没有发出另一个请求,服务器将终止连接
My problem is the following:
我的问题如下:
When I read from the NetworkStream object that I get from the TCPClient class, the NetworkStream Read() method does not block if there is no Data Available. When the server reaches step #3, I would like to set some timeout on the NetworkStream and if the client does not make any more requests within that duration the server should kill the connection when that timeout exception is thrown. When my server reaches step 3, the NetworkStream Read() method does not block, reguardless of what I set it's ReadTimeout property to be. Can anyone help me out, or suggest a better way to do what I'm trying to do.
当我从 TCPClient 类获取的 NetworkStream 对象中读取数据时,如果没有可用数据,NetworkStream Read() 方法不会阻塞。当服务器到达第 3 步时,我想在 NetworkStream 上设置一些超时,如果客户端在这段时间内没有发出更多请求,则服务器应该在抛出超时异常时终止连接。当我的服务器到达第 3 步时,NetworkStream Read() 方法不会阻塞,不管我将它的 ReadTimeout 属性设置为什么。任何人都可以帮助我,或提出更好的方法来做我想做的事情。
Thanks
谢谢
回答by Spencer Ruport
You should graduate from using Read() to the BeginRead()method and look into parallel processing. Network programming is not for the faint of heart.
您应该从使用 Read()过渡到使用BeginRead()方法并研究并行处理。网络编程不适合胆小的人。
Basically you don't want to create a loop polling for data.
基本上您不想为数据创建循环轮询。
while(!timedout && !stream.DataAvailable) sleep(0); // This is bad.
if(steam.DataAvailable) steam.Read();
Instead it makes more sense to do something like this. Create a reset event, call BeginRead(), and release the reset event on the callback. Something like the following:
相反,做这样的事情更有意义。创建一个重置事件,调用BeginRead(),并在回调上释放重置事件。类似于以下内容:
void clientThread()
{
stream.BeginRead(myCallback);
resetEvent.WaitOne(timeout)
}
void myCallback
{
resetEvent.Set();
}
回答by Reed Copsey
You'll need to handle the "timeout" yourself, since NetworkStream.Read() doesn't provide a way to do that.
您需要自己处理“超时”,因为 NetworkStream.Read() 不提供这样做的方法。
What you'll probably want to do in your client thread is use some combination of NetworkStream.DataAvailable and/or NetworkStream.CanRead in conjunction with a blocking/timeout mechanism (such as using a WaitHandle.WaitOne call with a timeout) to provide the client with time to make data available. If nothing comes in after a specified time, just shutdown the connection, and exit.
您可能希望在客户端线程中使用 NetworkStream.DataAvailable 和/或 NetworkStream.CanRead 的某种组合与阻塞/超时机制(例如使用带超时的 WaitHandle.WaitOne 调用)来提供客户有时间提供数据。如果在指定的时间后没有任何内容,则关闭连接并退出。
回答by Charlie
Wrap the NetworkStream in a BufferedStream. BufferedStream.Read will block until at least 1 byte is available.
将 NetworkStream 包装在 BufferedStream 中。BufferedStream.Read 将阻塞,直到至少有 1 个字节可用。
回答by Mirozell
NetworkStream.Read and ReadByte should block until the timeout if there's no data to read. I think it's far more likely that the call is reading something, probably a bunch of zeroes. Check the data being sent by the client carefully.
如果没有要读取的数据,NetworkStream.Read 和 ReadByte 应该阻塞直到超时。我认为调用正在读取某些内容的可能性要大得多,可能是一堆零。仔细检查客户端发送的数据。
回答by Amy
Is this what you're looking for?
这是你要找的吗?
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.receivetimeout.aspx
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.receivetimeout.aspx
Looks like you get the NetworkStream from the TcpClient using GetStream(), then call the Read() method on it.
看起来您使用 GetStream() 从 TcpClient 获取 NetworkStream,然后对其调用 Read() 方法。
回答by Linda Motaung
To explicitly force the NetworkStream to block when there is no available data:
在没有可用数据时明确强制 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;
}