Socket.AcceptAsync() と SocketAsyncEventArgs を使います。
using System; using System.Net; using System.Net.Sockets; using System.Diagnostics; namespace Samples { /// <summary> /// SocketAsyncEventArgs を使ったサーバー。 /// </summary> class SocketAsyncListener { Socket listener; public SocketAsyncListener() { Debug.WriteLine("Enter SocketAsyncListener::.ctor"); listener = null; Debug.WriteLine("Exit SocketAsyncListener::.ctor"); } public void Start() { if (listener != null) throw new InvalidOperationException(); Debug.WriteLine("Enter SocketAsyncListener::Start"); try { listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(IPAddress.Loopback, 8081)); // localhost:8081 listener.Listen(10); Debug.WriteLine(string.Format("Info SocketAsyncListener::Start listener#{0}", listener.GetHashCode())); } catch { if (listener != null) listener.Close(); listener = null; } finally { if (listener != null) BeginAccept(listener, null); Debug.WriteLine("Exit SocketAsyncListener::Start"); } } public void Stop() { if (listener == null) return; Debug.WriteLine("Enter SocketAsyncListener::Stop"); listener.Close(); listener = null; Debug.WriteLine("Exit SocketAsyncListener::Stop"); } private void BeginAccept(Socket listener, SocketAsyncEventArgs args) { Debug.WriteLine("Enter SocketAsyncListener::BeginAccept"); if (args == null) // null なら新しく作る。 { args = new SocketAsyncEventArgs(); args.Completed += new EventHandler<SocketAsyncEventArgs>(EndAccept); Debug.WriteLine(string.Format("Info SocketAsyncEventArgs#{0}", args.GetHashCode())); } args.AcceptSocket = null; // リセットしておく try { if (!listener.AcceptAsync(args)) EndAccept(listener, args); } catch (Exception ex) { Debug.WriteLine(string.Format("Exception SocketListener::BeginAccept {0}", ex.GetType().Name)); //throw ex; 何か問題があれば投げる? } finally { Debug.WriteLine("Exit SocketAsyncListener::BeginAccept"); } } private void EndAccept(object sender, SocketAsyncEventArgs e) { Debug.WriteLine("Enter SocketAsyncListener::EndAccept"); // SocketAsyncEventArgs の便利なところ。操作の結果がだいたいわかる if (e.SocketError == SocketError.OperationAborted) // listener が閉じられたので操作が中止された { Debug.WriteLine(string.Format("Info SocketAsyncListener::EndAccept listener#{0} is closed", sender.GetHashCode())); e.Dispose(); Debug.WriteLine(string.Format("Exit SocketAsyncListener::EndAccept SocketAsyncEventArgs#{0} is disposed", e.GetHashCode())); return; } Socket listener = (Socket)sender; Socket client = e.AcceptSocket; BeginAccept(listener, e); // 次へ Debug.WriteLine("Exit SocketAsyncListener::EndAccept"); // ここでクライアントと通信する。 // とりあえず今回は閉じるだけ。 client.Close(); } } }