public RioTcpServer(ushort port, byte address1, byte address2, byte address3, byte address4) { var version = new Internal.Winsock.Version(2, 2); WindowsSocketsData wsaData; System.Net.Sockets.SocketError result = RioImports.WSAStartup((short)version.Raw, out wsaData); if (result != System.Net.Sockets.SocketError.Success) { var error = RioImports.WSAGetLastError(); throw new Exception(string.Format("ERROR: WSAStartup returned {0}", error)); } _socket = RioImports.WSASocket(AddressFamilies.Internet, SocketType.Stream, Protocol.IpProtocolTcp, IntPtr.Zero, 0, SocketFlags.RegisteredIO); if (_socket == IntPtr.Zero) { var error = RioImports.WSAGetLastError(); RioImports.WSACleanup(); throw new Exception(string.Format("ERROR: WSASocket returned {0}", error)); } _rio = RioImports.Initalize(_socket); _pool = new RioThreadPool(_rio, _socket, CancellationToken.None); _connectionId = 0; Start(port, address1, address2, address3, address4); }
private static void ThrowError(ErrorType type) { var errorNo = RioImports.WSAGetLastError(); string errorMessage; switch (errorNo) { case 10014: // WSAEFAULT errorMessage = $"{type} failed: WSAEFAULT - The system detected an invalid pointer address in attempting to use a pointer argument in a call."; break; case 10022: // WSAEINVAL errorMessage = $"{type} failed: WSAEINVAL - the SocketQueue parameter is not valid, the Flags parameter contains an value not valid for a send operation, or the integrity of the completion queue has been compromised."; break; case 10055: // WSAENOBUFS errorMessage = $"{type} failed: WSAENOBUFS - Sufficient memory could not be allocated, the I/O completion queue associated with the SocketQueue parameter is full."; break; case 997: // WSA_IO_PENDING errorMessage = $"{type} failed? WSA_IO_PENDING - The operation has been successfully initiated and the completion will be queued at a later time."; break; case 995: // WSA_OPERATION_ABORTED errorMessage = $"{type} failed. WSA_OPERATION_ABORTED - The operation has been canceled while the receive operation was pending."; break; default: errorMessage = $"{type} failed: WSA error code {errorNo}"; break; } throw new InvalidOperationException(errorMessage); }
public RioTcpConnection Accept() { var accepted = RioImports.accept(_socket, IntPtr.Zero, 0); if (accepted == new IntPtr(-1)) { var error = RioImports.WSAGetLastError(); RioImports.WSACleanup(); throw new Exception($"listen failed with {error}"); } var connectionId = Interlocked.Increment(ref _connectionId); var thread = _pool.GetThread(connectionId); var requestQueue = _rio.RioCreateRequestQueue( accepted, maxOutstandingReceive: MaxReadsPerSocket, maxReceiveDataBuffers: 1, maxOutstandingSend: MaxWritesPerSocket, maxSendDataBuffers: 1, receiveCq: thread.ReceiveCompletionQueue, sendCq: thread.SendCompletionQueue, connectionCorrelation: connectionId); if (requestQueue == IntPtr.Zero) { var error = RioImports.WSAGetLastError(); RioImports.WSACleanup(); throw new Exception($"ERROR: RioCreateRequestQueue returned {error}"); } return(new RioTcpConnection(accepted, connectionId, requestQueue, thread, _rio)); }
private void Dispose(bool disposing) { if (!_disposedValue) { _rioThread.RemoveConnection(_connectionId); RioImports.closesocket(_socket); _disposedValue = true; } }
public unsafe RioThreadPool(RegisteredIO rio, IntPtr socket, CancellationToken token) { _socket = socket; _rio = rio; _token = token; // Count non-HT cores only var procCount = CpuInfo.PhysicalCoreCount; // RSS only supports up to 16 cores _maxThreads = procCount > 16 ? 16 : procCount; _rioThreads = new RioThread[_maxThreads]; for (var i = 0; i < _rioThreads.Length; i++) { IntPtr completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, IntPtr.Zero, 0, 0); if (completionPort == IntPtr.Zero) { var error = GetLastError(); RioImports.WSACleanup(); throw new Exception($"ERROR: CreateIoCompletionPort returned {error}"); } var completionMethod = new NotificationCompletion { Type = NotificationCompletionType.IocpCompletion, Iocp = new NotificationCompletionIocp { IocpHandle = completionPort, QueueCorrelation = (ulong)i, Overlapped = (NativeOverlapped *)(-1) // nativeOverlapped } }; IntPtr completionQueue = _rio.RioCreateCompletionQueue(RioTcpServer.MaxOutsandingCompletionsPerThread, completionMethod); if (completionQueue == IntPtr.Zero) { var error = RioImports.WSAGetLastError(); RioImports.WSACleanup(); throw new Exception($"ERROR: RioCreateCompletionQueue returned {error}"); } var thread = new RioThread(i, _token, completionPort, completionQueue, rio); _rioThreads[i] = thread; } for (var i = 0; i < _rioThreads.Length; i++) { var thread = _rioThreads[i]; thread.Start(); } }
private void Dispose(bool disposing) { if (!_disposedValue) { RioTcpConnection connection; _rioThread.Connections.TryRemove(_connectionId, out connection); RioImports.closesocket(_socket); _disposedValue = true; } }
public unsafe RioThreadPool(RegisteredIO rio, IntPtr socket, CancellationToken token) { _socket = socket; _rio = rio; _token = token; _maxThreads = Environment.ProcessorCount; _rioThreads = new RioThread[_maxThreads]; for (var i = 0; i < _rioThreads.Length; i++) { IntPtr completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, IntPtr.Zero, 0, 0); if (completionPort == IntPtr.Zero) { var error = GetLastError(); RioImports.WSACleanup(); throw new Exception(string.Format("ERROR: CreateIoCompletionPort returned {0}", error)); } var completionMethod = new NotificationCompletion() { Type = NotificationCompletionType.IocpCompletion, Iocp = new NotificationCompletionIocp() { IocpHandle = completionPort, QueueCorrelation = (ulong)i, Overlapped = (NativeOverlapped *)(-1)// nativeOverlapped } }; IntPtr completionQueue = _rio.RioCreateCompletionQueue(RioTcpServer.MaxOutsandingCompletionsPerThread, completionMethod); if (completionQueue == IntPtr.Zero) { var error = RioImports.WSAGetLastError(); RioImports.WSACleanup(); throw new Exception(String.Format("ERROR: RioCreateCompletionQueue returned {0}", error)); } var thread = new RioThread(i, _token, completionPort, completionQueue, rio); _rioThreads[i] = thread; } for (var i = 0; i < _rioThreads.Length; i++) { var thread = _rioThreads[i]; thread.Start(); } }
private void Start(ushort port, byte address1, byte address2, byte address3, byte address4) { // BIND var inAddress = new Ipv4InternetAddress(); inAddress.Byte1 = address1; inAddress.Byte2 = address2; inAddress.Byte3 = address3; inAddress.Byte4 = address4; var sa = new SocketAddress(); sa.Family = AddressFamilies.Internet; sa.Port = RioImports.htons(port); sa.IpAddress = inAddress; int result; unsafe { var size = sizeof(SocketAddress); result = RioImports.bind(_socket, ref sa, size); } if (result == RioImports.SocketError) { RioImports.WSACleanup(); throw new Exception("bind failed"); } // LISTEN result = RioImports.listen(_socket, 2048); if (result == RioImports.SocketError) { RioImports.WSACleanup(); throw new Exception("listen failed"); } }
public void Stop() { RioImports.WSACleanup(); }