我用下面的代码来创建一个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