我用下面的代碼來創建一個assyncronous TCP服務器:Assync TCP服務器的代碼示例分析
private void SetupServerSocket()
{
var myEndpoint = new IPEndPoint(IPAddress.Any, _port);
_serverSocket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
_serverSocket.Bind(myEndpoint);
_serverSocket.Listen((int)SocketOptionName.MaxConnections);
}
protected void Open()
{
SetupServerSocket();
Opened = true;
_serverSocket.BeginAccept(AcceptCallback, _serverSocket);
}
private void AcceptCallback(IAsyncResult result)
{
var connection = new ConnectionInfo();
try
{
// Finish Accept
var s = (Socket)result.AsyncState;
connection.Socket = s.EndAccept(result);
connection.Buffer = new byte[8192];
lock (_connections)
{
_connections.Add(connection);
}
// Start Receive and a new Accept
connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.None, ReceiveCallback, connection);
_serverSocket.BeginAccept(AcceptCallback, result.AsyncState);
}
catch (SocketException ex)
{
CloseConnection(connection);
}
catch (Exception ex)
{
CloseConnection(connection);
}
}
private void CloseConnection(ConnectionInfo ci)
{
if (ci.Socket != null)
{
if (OnDisconnect != null)
OnDisconnect.Invoke((IPEndPoint)ci.Socket.RemoteEndPoint);
ci.Socket.Shutdown(SocketShutdown.Both);
ci.Socket.Close();
}
lock (_connections)
{
_connections.Remove(ci);
}
}
有一些事情是很難理解:
1 - 使用_serverSocket.SetSocketOption
我啓用在TCP中使用KeepAlive。我發現默認情況下Windows的默認KeepAlive Timer爲2小時!並使用Wireshark確認此行爲。
經過一些Google搜索後,我在http://support.microsoft.com/kb/120642/EN-US中發現,您可以通過在註冊表中創建一個密鑰來更改Windows KeepAliveTime。我確實喜歡這個支持頁面指示,但KeepAlive Timer沒有應用(即使在重新啓動後),它仍然是2個小時。有誰知道如何更改Windows中的KeepAlive Timer?
2 - 代碼connection.Socket = s.EndAccept(result)
可以拋出異常(通常是SocketException)。爲什麼Socket.EndResult
會拋出SocketException
?
3 - 爲什麼我們必須將_serverSocket
再次設置爲接受狀態,如果AcceptCallback()
已經處於該狀態?
謝謝
在MSDN文檔中說,BeginAccept只會觸發一次回調? – RHaguiuda 2013-02-22 11:44:08
「對於每個異步請求,此方法被調用一次」 - http://msdn.microsoft.com/en-us/library/system.asynccallback.aspx – MarcF 2013-02-22 11:49:10
我可以在_serverSocket.BeginAccept(AcceptCallback,result.AsyncState)中設置AcceptCallback方法的第一行來保證服務器套接字將返回到Accept狀態? – RHaguiuda 2013-02-22 11:51:46