次のコードを使用して、非同期 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 の既定のキープアライブ タイマーは 2 時間であることがわかりました。この動作は Wireshark を使用して確認されました。
いくつかのグーグル検索の後、http://support.microsoft.com/kb/120642/EN-USで、レジストリにキーを作成することで Windows KeepAliveTime を変更できることがわかりました。このサポート ページの指示が気に入りましたが、KeepAlive タイマーが適用されず (再起動後も)、まだ 2 時間です。Windowsでキープアライブタイマーを変更する方法を知っている人はいますか?
2 - コードconnection.Socket = s.EndAccept(result)
は例外をスローできます (通常は SocketException)。なぜSocket.EndResult
投げるのSocketException
ですか?
3 -既に_serverSocket
Accept 状態にあるのに、再度 Accept 状態に設定する必要があるのはなぜですか?AcceptCallback()
ありがとうございました