.NET Framework で実装されている Begin/End パターンを使ってサーバーを作ってみました。
今回はクライアントと接続するだけです。クライアントとの通信処理は実装していません。
using System; using System.Net; using System.Net.Sockets; using System.Diagnostics; namespace Samples { /// <summary> /// Begin/End パターンを使った Tcp サーバー。 /// </summary> class BeginEndListener { Socket listener; public BeginEndListener() { listener = null; } public void Start() { if (listener != null) // Start() -> Start() とかした場合 throw new InvalidOperationException(); Debug.WriteLine("Enter BeginEndListener::Start"); try { listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(IPAddress.Loopback, 8081)); listener.Listen(10); } catch (Exception e) { if (listener != null) listener.Close(); listener = null; // null に戻す Debug.WriteLine("Exception BeginEndListener::Start " + e.Message); // throw e; 投げてもいい。投げない場合は IsListening で確認 } finally { if (listener != null) { Debug.WriteLine(string.Format("Info listener#{0}", listener.GetHashCode())); listener.BeginAccept(EndAccept, listener); } Debug.WriteLine("Exit BeginEndListener::Start"); } } public void Stop() { if (listener == null) return; Debug.WriteLine("Enter BeginEndListener::Stop"); listener.Close(); listener = null; Debug.WriteLine("Exit BeginEndListener::Stop"); } private void EndAccept(IAsyncResult ar) { Debug.WriteLine("Enter BeginEndListener::EndAccept"); // if (IsListening) return; とかはしない。同期とるよりも listener が閉じられてたら例外を拾った方が簡単。 Socket listener = ar.AsyncState as Socket; // 必ず呼び出した listener を使う Socket client = null; try { listener.BeginAccept(EndAccept, listener); // すぐに次へ client = listener.EndAccept(ar); } catch (Exception e) { if (e is ObjectDisposedException) Debug.WriteLine(string.Format("Exception BeginEndListener::EndAccept listener({0}) is closed", listener.GetHashCode())); else Debug.WriteLine("Exception BeginEndListener::EndAccept {0}", e.GetType().ToString()); } finally { Debug.WriteLine("Exit BeginEndListener::EndAccept"); // ここでクライアントと通信する。 // とりあえず今回は閉じるだけ。 if (client != null) client.Close(); // Connection conn = new Connection(client) // while (conn.Connected) // { // HandleRequest(conn); // } } } } }