예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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));
        }
예제 #4
0
        private void Dispose(bool disposing)
        {
            if (!_disposedValue)
            {
                _rioThread.RemoveConnection(_connectionId);
                RioImports.closesocket(_socket);

                _disposedValue = true;
            }
        }
예제 #5
0
        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();
            }
        }
예제 #6
0
        private void Dispose(bool disposing)
        {
            if (!_disposedValue)
            {
                RioTcpConnection connection;
                _rioThread.Connections.TryRemove(_connectionId, out connection);
                RioImports.closesocket(_socket);

                _disposedValue = true;
            }
        }
예제 #7
0
        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();
            }
        }
예제 #8
0
        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");
            }
        }
예제 #9
0
 public void Stop()
 {
     RioImports.WSACleanup();
 }