所以,必须等客户端先关闭Socket后,服务器端再关闭Socket才能避免TIME_WAIT状态的出现。
判断客户端Socket的关闭
最近试验发现,当客户端Socket关闭时,服务端的Socket会接收到0字节的通知。
private int Receive(StringBuilder sb)
{
int read = 0, total = 0
if (_Client != null)
{
try
{
byte[] bytes = new byte[SIZE]
int available = _Client.Available
do
{
read = _Client.Receive(bytes)//如果客户端Socket关闭,_Client会接受到read=0
total += read
if (read >0)
sb.Append(_Server.DefaultEncoding.GetString(bytes, 0, read))
} while (read >0 &&total <available)
}
catch (SocketException)
{
CloseSocket()
}
}
if (_Server.TraceInConsole &&total >0)
{
Console.WriteLine("Receive:" + total + "======================================")
Console.WriteLine(sb.ToString())
}
return total
}
利用0字节接收条件判断客户端Socket的关闭,开始执行服务端Socket关闭代码。
private void ThreadHandler()
{
if (_Server.TraceInConsole)
Console.WriteLine("Begin HttpRequest...")
try
{
while (true)
{
StringBuilder sb = new StringBuilder()
int receive = Receive(sb)
if (receive >0)
{
_Server.ReadRequest(this, sb.ToString())
_Server.Response(this)
_Server.ResponseFinished(this)
}
else
{
TryCloseSocket()
}
if (_Client == null)
break
}
}
catch (Exception ex)
{
if (_Server.TraceInConsole)
Console.WriteLine(ex.Message)
}
if (_Server.TraceInConsole)
Console.WriteLine(" www.hbbz08.com End HttpRequest.")
}
服务端Socket的关闭
如果直接调用Socket的Close方法会关闭得太快,可能导致客户端TIME_WAIT现象;而Thead.Sleep延时再调用Socket的Close方法也不理想。应该采用尝试向客户端发送数据,然后利用异常来关闭Socket,方法如下。
private void TryCloseSocket()
{
try
{
while (true)
{
Thread.Sleep(1500)
Send(HttpServer.BYTES_CRLF)//发送自定义的字节,如果客户端关闭出现SocketException,然后关闭服务端Socket
if (_Client == null)
break
}
}
catch (SocketException)
{
CloseSocket()
}
}
private void CloseSocket()
{
if (_Client != null)
{
_Client.Shutdown(SocketShutdown.Both)
_Client.Close()
_Client = null
if (_Server.TraceInConsole)
{
Console.WriteLine("Close socket.")
}
}
}
使用WSAGetOverlappedResult()函数,看一下具体的错误代码是什么!在GetQueuedCompletionStatus返回错误,用WSAGetLastError()得到的并不是真正的错误代码!
估计是资源申请或释放方面的问题,如,资源不够!
你每个连接上投递了多少个异步发送接收请求?
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)