public void WorkerThread() { while (true) { IntPtr addressOfPerHandleData; IntPtr addressOfOverlapped; uint transferredBytes; // Get! bool result = GetQueuedCompletionStatus(mCompletionPort, out transferredBytes, out addressOfPerHandleData, out addressOfOverlapped, uint.MaxValue); if (result == false) { Console.WriteLine("GetQueuedCompletionStatus Error! : " + WSAGetLastError()); Thread.Sleep(1000); continue; } // Retrive data GCHandle gchPerHandleData = GCHandle.FromIntPtr(addressOfPerHandleData); PerHandleData perHandleData = (PerHandleData)gchPerHandleData.Target; Overlapped overlapped = new Overlapped(); Marshal.PtrToStructure(addressOfOverlapped, overlapped); PerIoData perIoData = (PerIoData)overlapped.mGCHPerIoData.Target; switch (perIoData.mType) { case OperationType.OT_DISCONNECT: break; case OperationType.OT_RECEIVE: Interlocked.Add(ref mTotalRecvBytes, transferredBytes); Console.WriteLine("ReceiveData Success! (Total bytes : " + mTotalRecvBytes + ")"); ReceiveData(perHandleData.mSocket); break; case OperationType.OT_SEND: break; } // Release perIoData perIoData.mGCHBuffer.Free(); perIoData.mGCHOverlapped.Free(); overlapped.mGCHPerIoData.Free(); // Disconnect (Release perHandleData) if (transferredBytes == 0) { perHandleData.mThis.Free(); } } }
public void Start() { // Initialize WS WSAData wsaData; if (WSAStartup(0x0202, out wsaData) != SocketError.Success) { Console.WriteLine("WSAStartup Error! : " + WSAGetLastError()); return; } // Create completion port mCompletionPort = CreateIoCompletionPort(new IntPtr(-1), IntPtr.Zero, IntPtr.Zero, 0); if (mCompletionPort.IsInvalid) { Console.WriteLine("CreateIoCompletionPort Error! : " + WSAGetLastError()); return; } // Create listen socket mListenSocket = WSASocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, IntPtr.Zero, 0, SocketConstructorFlags.WSA_FLAG_OVERLAPPED); if (mListenSocket.ToInt32() == 0) { Console.WriteLine("WSASocket Error! : " + WSAGetLastError()); return; } // Bind address IPEndPoint address = new IPEndPoint(IPAddress.Any, 9001); FieldInfo bufferFieldInfo = typeof(SocketAddress).GetField("m_Buffer", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo sizeFieldInfo = typeof(SocketAddress).GetField("m_Size", BindingFlags.Instance | BindingFlags.NonPublic); mMyAddress = (byte[])bufferFieldInfo.GetValue(address.Serialize()); mMyAddressSize = (int)sizeFieldInfo.GetValue(address.Serialize()); if (bind(mListenSocket, mMyAddress, mMyAddressSize) != SocketError.Success) { Console.WriteLine("bind Error! : " + WSAGetLastError()); return; } // Listen if (listen(mListenSocket, 128) != SocketError.Success) { Console.WriteLine("listen Error! : " + WSAGetLastError()); return; } // Create worker thread and run CreateWorkerThread(WORKER_THREAD_COUNT); // Accept loop while (true) { // Accept (Wait...) IntPtr acceptedSocket; acceptedSocket = accept(mListenSocket, mMyAddress, ref mMyAddressSize); // Welcome! PerHandleData perHandleData = new PerHandleData(); GCHandle gchPerHandleData = GCHandle.Alloc(perHandleData, GCHandleType.Pinned); perHandleData.mSocket = acceptedSocket; perHandleData.mThis = gchPerHandleData; // Assign socket to completion port CreateIoCompletionPort(acceptedSocket, mCompletionPort.DangerousGetHandle(), GCHandle.ToIntPtr(gchPerHandleData), 0); // Change socket options /* * Object socketRecvBufferSize = 0; * int oldSocketRecvBufferSize = 0; * getsockopt(acceptedSocket, SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, ref socketRecvBufferSize, ref oldSocketRecvBufferSize); * ... */ // Receive ReceiveData(acceptedSocket); } }