我有一个代码,使用异步套接字向客户端发送消息并期待来自它的响应。如果客户端没有在指定的内部回复,则会考虑超时。 Internet上的一些文章建议使用WaitOne,但这会阻塞线程并推迟使用I / O完成的目的。
在异步套接字中处理超时的最佳方法是什么?
Sub OnSend(ByVal ar As IAsyncResult)
Dim socket As Socket = CType(ar.AsyncState ,Socket)
socket.EndSend(ar)
socket.BeginReceive(Me.ReceiveBuffer, 0, Me.ReceiveBuffer.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), socket)
End Sub
答案 0 :(得分:7)
您无法超时或取消异步Socket
操作。
您所能做的只是启动自己的Timer
关闭Socket
- 然后会立即调用回调,EndX
函数将返回ObjectDisposedException
如果你打电话的话。这是一个例子:
using System;
using System.Threading;
using System.Net.Sockets;
class AsyncClass
{
Socket sock;
Timer timer;
byte[] buffer;
int timeoutflag;
public AsyncClass()
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
buffer = new byte[256];
}
public void StartReceive()
{
IAsyncResult res = sock.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, OnReceive, null);
if(!res.IsCompleted)
{
timer = new Timer(OnTimer, null, 1000, Timeout.Infinite);
}
}
void OnReceive(IAsyncResult res)
{
if(Interlocked.CompareExchange(ref timeoutflag, 1, 0) != 0)
{
// the flag was set elsewhere, so return immediately.
return;
}
// we set the flag to 1, indicating it was completed.
if(timer != null)
{
// stop the timer from firing.
timer.Dispose();
}
// process the read.
int len = sock.EndReceive(res);
}
void OnTimer(object obj)
{
if(Interlocked.CompareExchange(ref timeoutflag, 2, 0) != 0)
{
// the flag was set elsewhere, so return immediately.
return;
}
// we set the flag to 2, indicating a timeout was hit.
timer.Dispose();
sock.Close(); // closing the Socket cancels the async operation.
}
}