Пример #1
0
        public RIOTcpServer(ushort port, byte address1, byte address2, byte address3, byte address4)
        {
            var version = new RIOTcpServer.Version(2, 2);
            WSAData data;
            SocketError result = RIOImports.WSAStartup((short)version.Raw, out data);
            if (result != SocketError.Success)
            {
                var error = RIOImports.WSAGetLastError();
                throw new Exception(String.Format("ERROR: WSAStartup returned {0}", error));
            }

            _socket = RIOImports.WSASocket(ADDRESS_FAMILIES.AF_INET, SOCKET_TYPE.SOCK_STREAM, PROTOCOL.IPPROTO_TCP, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO);
            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
        public RIOTcpServer(ushort port, byte address1, byte address2, byte address3, byte address4)
        {
            var         version = new RIOTcpServer.Version(2, 2);
            WSAData     data;
            SocketError result = RIOImports.WSAStartup((short)version.Raw, out data);

            if (result != SocketError.Success)
            {
                var error = RIOImports.WSAGetLastError();
                throw new Exception(String.Format("ERROR: WSAStartup returned {0}", error));
            }

            _socket = RIOImports.WSASocket(ADDRESS_FAMILIES.AF_INET, SOCKET_TYPE.SOCK_STREAM, PROTOCOL.IPPROTO_TCP, IntPtr.Zero, 0, SOCKET_FLAGS.REGISTERED_IO);
            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);
        }
Пример #3
0
        public RIOBufferPool(RIO rio)
        {
            _rio = rio;
            _allocatedBuffers  = new ConcurrentQueue <AllocatedBuffer>();
            _availableSegments = new ConcurrentQueue <int>();

            _underlyingBuffer = new byte[BufferLength];
        }
Пример #4
0
        public RIOBufferPool(RIO rio)
        {
            _rio = rio;
            _allocatedBuffers = new ConcurrentQueue<AllocatedBuffer>();
            _availableSegments = new ConcurrentQueue<int>();

            _underlyingBuffer = new byte[BufferLength];
            
        }
Пример #5
0
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                AllocatedBuffer buffer;
                while (_allocatedBuffers.TryDequeue(out buffer))
                {
                    _rio.DeregisterBuffer(buffer.BufferId);
                    buffer.PinnedBuffer.Free();
                }

                if (disposing)
                {
                    _segments         = null;
                    _underlyingBuffer = null;
                    _rio = null;
                    _availableSegments = null;
                    _allocatedBuffers  = null;
                }

                disposedValue = true;
            }
        }
Пример #6
0
        internal TcpConnection(IntPtr socket, long connectionId, WorkBundle wb, RIO rio)
        {
            _socket       = socket;
            _connectionId = connectionId;
            _rio          = rio;
            _wb           = wb;

            _requestQueue = _rio.CreateRequestQueue(_socket, MaxPendingReceives, 1, MaxPendingSends, 1, wb.completionQueue, wb.completionQueue, connectionId);
            if (_requestQueue == IntPtr.Zero)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: CreateRequestQueue returned {0}", error));
            }

            _receiveTasks          = new ReceiveTask[MaxPendingReceives];
            _receiveRequestBuffers = new ArraySegment <byte> [MaxPendingReceives];

            for (var i = 0; i < _receiveTasks.Length; i++)
            {
                _receiveTasks[i] = new ReceiveTask(this, wb.bufferPool.GetBuffer());
            }

            _sendSegments = new PooledSegment[MaxPendingSends];
            for (var i = 0; i < _sendSegments.Length; i++)
            {
                _sendSegments[i] = wb.bufferPool.GetBuffer();
            }

            wb.connections.TryAdd(connectionId, this);

            for (var i = 0; i < _receiveTasks.Length; i++)
            {
                PostReceive(i);
            }
        }
Пример #7
0
        internal TcpConnection(IntPtr socket, long connectionId, WorkBundle wb, RIO rio)
        {
            _socket = socket;
            _connectionId = connectionId;
            _rio = rio;
            _wb = wb;

            _requestQueue = _rio.CreateRequestQueue(_socket, MaxPendingReceives, 1, MaxPendingSends, 1, wb.completionQueue, wb.completionQueue, connectionId);
            if (_requestQueue == IntPtr.Zero)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: CreateRequestQueue returned {0}", error));
            }

            _receiveTasks = new ReceiveTask[MaxPendingReceives];
            _receiveRequestBuffers = new ArraySegment<byte>[MaxPendingReceives];

            for (var i = 0; i < _receiveTasks.Length; i++)
            {
                _receiveTasks[i] = new ReceiveTask(this, wb.bufferPool.GetBuffer());
            }

            _sendSegments = new PooledSegment[MaxPendingSends];
            for (var i = 0; i < _sendSegments.Length; i++)
            {
                _sendSegments[i] = wb.bufferPool.GetBuffer();
            }

            wb.connections.TryAdd(connectionId, this);

            for (var i = 0; i < _receiveTasks.Length; i++)
            {
                PostReceive(i);
            }
        }
Пример #8
0
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                AllocatedBuffer buffer;
                while (_allocatedBuffers.TryDequeue(out buffer))
                {
                    _rio.DeregisterBuffer(buffer.BufferId);
                    buffer.PinnedBuffer.Free();
                }

                if (disposing)
                {
                    _segments = null;
                    _underlyingBuffer = null;
                    _rio = null;
                    _availableSegments = null;
                    _allocatedBuffers = null;
                }

                disposedValue = true;
            }
        }
Пример #9
0
        public unsafe static RIO Initalize(IntPtr socket)
        {
            UInt32 dwBytes = 0;
            RIO_EXTENSION_FUNCTION_TABLE rio = new RIO_EXTENSION_FUNCTION_TABLE();
            Guid RioFunctionsTableId         = new Guid("8509e081-96dd-4005-b165-9e2ee8c79e3f");


            int True = -1;

            int result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&True, 4);

            if (result != 0)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: setsockopt TCP_NODELAY returned {0}", error));
            }

            result = WSAIoctlGeneral(socket, SIO_LOOPBACK_FAST_PATH,
                                     &True, 4, null, 0,
                                     out dwBytes, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: WSAIoctl SIO_LOOPBACK_FAST_PATH returned {0}", error));
            }

            result = WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
                              ref RioFunctionsTableId, 16, ref rio,
                              sizeof(RIO_EXTENSION_FUNCTION_TABLE),
                              out dwBytes, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: RIOInitalize returned {0}", error));
            }
            else
            {
                RIO rioFunctions = new RIO();

                rioFunctions.RegisterBuffer = Marshal.GetDelegateForFunctionPointer <RIORegisterBuffer>(rio.RIORegisterBuffer);

                rioFunctions.CreateCompletionQueue = Marshal.GetDelegateForFunctionPointer <RIOCreateCompletionQueue>(rio.RIOCreateCompletionQueue);

                rioFunctions.CreateRequestQueue = Marshal.GetDelegateForFunctionPointer <RIOCreateRequestQueue>(rio.RIOCreateRequestQueue);

                rioFunctions.Notify            = Marshal.GetDelegateForFunctionPointer <RIONotify>(rio.RIONotify);
                rioFunctions.DequeueCompletion = Marshal.GetDelegateForFunctionPointer <RIODequeueCompletion>(rio.RIODequeueCompletion);

                rioFunctions.Receive = Marshal.GetDelegateForFunctionPointer <RIOReceive>(rio.RIOReceive);
                rioFunctions.Send    = Marshal.GetDelegateForFunctionPointer <RIOSend>(rio.RIOSend);

                rioFunctions.CloseCompletionQueue  = Marshal.GetDelegateForFunctionPointer <RIOCloseCompletionQueue>(rio.RIOCloseCompletionQueue);
                rioFunctions.DeregisterBuffer      = Marshal.GetDelegateForFunctionPointer <RIODeregisterBuffer>(rio.RIODeregisterBuffer);
                rioFunctions.ResizeCompletionQueue = Marshal.GetDelegateForFunctionPointer <RIOResizeCompletionQueue>(rio.RIOResizeCompletionQueue);
                rioFunctions.ResizeRequestQueue    = Marshal.GetDelegateForFunctionPointer <RIOResizeRequestQueue>(rio.RIOResizeRequestQueue);

                return(rioFunctions);
            }
        }
Пример #10
0
        public unsafe RIOThreadPool(RIO rio, IntPtr socket, CancellationToken token)
        {
            _socket = socket;
            _rio = rio;
            _token = token;

            _maxThreads = Environment.ProcessorCount;

            _workers = new WorkBundle[_maxThreads];
            for (var i = 0; i < _workers.Length; i++)
            {
                var worker = new WorkBundle()
                {
                    id = i,
                    bufferPool = new RIOBufferPool(_rio)
                };
                worker.completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, IntPtr.Zero, 0, 0);

                if (worker.completionPort == IntPtr.Zero)
                {
                    var error = GetLastError();
                    RIOImports.WSACleanup();
                    throw new Exception(String.Format("ERROR: CreateIoCompletionPort returned {0}", error));
                }

                var completionMethod = new RIO_NOTIFICATION_COMPLETION()
                {
                    Type = RIO_NOTIFICATION_COMPLETION_TYPE.IOCP_COMPLETION,
                    Iocp = new RIO_NOTIFICATION_COMPLETION_IOCP()
                    {
                        IocpHandle = worker.completionPort,
                        QueueCorrelation = (ulong)i,
                        Overlapped = (NativeOverlapped*)(-1)// nativeOverlapped
                    }
                };
                worker.completionQueue = _rio.CreateCompletionQueue(MaxOutsandingCompletions, completionMethod);

                if (worker.completionQueue == IntPtr.Zero)
                {
                    var error = RIOImports.WSAGetLastError();
                    RIOImports.WSACleanup();
                    throw new Exception(String.Format("ERROR: CreateCompletionQueue returned {0}", error));
                }

                worker.connections = new ConcurrentDictionary<long, TcpConnection>();
                worker.thread = new Thread(GetThreadStart(i));
                worker.thread.IsBackground = true;
                _workers[i] = worker;
            }

            // gc
            //GC.Collect(2, GCCollectionMode.Forced, true, true);
            //GC.WaitForPendingFinalizers();
            //GC.Collect(2, GCCollectionMode.Forced, true, true);

            GC.Collect(2, GCCollectionMode.Forced, true);
            GC.WaitForPendingFinalizers();
            GC.Collect(2, GCCollectionMode.Forced, true);

            for (var i = 0; i < _workers.Length; i++)
            {
                // pin buffers
                _workers[i].bufferPool.Initalize();
            }


            for (var i = 0; i < _workers.Length; i++)
            {
                _workers[i].thread.Start();
            }
        }
Пример #11
0
        public unsafe RIOThreadPool(RIO rio, IntPtr socket, CancellationToken token)
        {
            _socket = socket;
            _rio    = rio;
            _token  = token;

            _maxThreads = Environment.ProcessorCount;

            _workers = new WorkBundle[_maxThreads];
            for (var i = 0; i < _workers.Length; i++)
            {
                var worker = new WorkBundle()
                {
                    id         = i,
                    bufferPool = new RIOBufferPool(_rio)
                };
                worker.completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, IntPtr.Zero, 0, 0);

                if (worker.completionPort == IntPtr.Zero)
                {
                    var error = GetLastError();
                    RIOImports.WSACleanup();
                    throw new Exception(String.Format("ERROR: CreateIoCompletionPort returned {0}", error));
                }

                var completionMethod = new RIO_NOTIFICATION_COMPLETION()
                {
                    Type = RIO_NOTIFICATION_COMPLETION_TYPE.IOCP_COMPLETION,
                    Iocp = new RIO_NOTIFICATION_COMPLETION_IOCP()
                    {
                        IocpHandle       = worker.completionPort,
                        QueueCorrelation = (ulong)i,
                        Overlapped       = (NativeOverlapped *)(-1)// nativeOverlapped
                    }
                };
                worker.completionQueue = _rio.CreateCompletionQueue(MaxOutsandingCompletions, completionMethod);

                if (worker.completionQueue == IntPtr.Zero)
                {
                    var error = RIOImports.WSAGetLastError();
                    RIOImports.WSACleanup();
                    throw new Exception(String.Format("ERROR: CreateCompletionQueue returned {0}", error));
                }

                worker.connections         = new ConcurrentDictionary <long, TcpConnection>();
                worker.thread              = new Thread(GetThreadStart(i));
                worker.thread.IsBackground = true;
                _workers[i] = worker;
            }

            // gc
            //GC.Collect(2, GCCollectionMode.Forced, true, true);
            //GC.WaitForPendingFinalizers();
            //GC.Collect(2, GCCollectionMode.Forced, true, true);

            GC.Collect(2, GCCollectionMode.Forced, true);
            GC.WaitForPendingFinalizers();
            GC.Collect(2, GCCollectionMode.Forced, true);

            for (var i = 0; i < _workers.Length; i++)
            {
                // pin buffers
                _workers[i].bufferPool.Initalize();
            }


            for (var i = 0; i < _workers.Length; i++)
            {
                _workers[i].thread.Start();
            }
        }
Пример #12
0
        public unsafe static RIO Initalize(IntPtr socket)
        {

            UInt32 dwBytes = 0;
            RIO_EXTENSION_FUNCTION_TABLE rio = new RIO_EXTENSION_FUNCTION_TABLE();
            Guid RioFunctionsTableId = new Guid("8509e081-96dd-4005-b165-9e2ee8c79e3f");


            int True = -1;

            int result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&True, 4);
            if (result != 0)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: setsockopt TCP_NODELAY returned {0}", error));
            }

            result = WSAIoctlGeneral(socket, SIO_LOOPBACK_FAST_PATH, 
                                &True, 4, null, 0,
                                out dwBytes, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: WSAIoctl SIO_LOOPBACK_FAST_PATH returned {0}", error));
            }

            result = WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
               ref RioFunctionsTableId, 16, ref rio,
               sizeof(RIO_EXTENSION_FUNCTION_TABLE),
               out dwBytes, IntPtr.Zero, IntPtr.Zero);
            
            if (result != 0)
            {
                var error = RIOImports.WSAGetLastError();
                RIOImports.WSACleanup();
                throw new Exception(String.Format("ERROR: RIOInitalize returned {0}", error));
            }
            else
            {
                RIO rioFunctions = new RIO();

                rioFunctions.RegisterBuffer = Marshal.GetDelegateForFunctionPointer<RIORegisterBuffer>(rio.RIORegisterBuffer);

                rioFunctions.CreateCompletionQueue = Marshal.GetDelegateForFunctionPointer<RIOCreateCompletionQueue>(rio.RIOCreateCompletionQueue);

                rioFunctions.CreateRequestQueue = Marshal.GetDelegateForFunctionPointer<RIOCreateRequestQueue>(rio.RIOCreateRequestQueue);
                
                rioFunctions.Notify = Marshal.GetDelegateForFunctionPointer<RIONotify>(rio.RIONotify);
                rioFunctions.DequeueCompletion = Marshal.GetDelegateForFunctionPointer<RIODequeueCompletion>(rio.RIODequeueCompletion);

                rioFunctions.Receive = Marshal.GetDelegateForFunctionPointer<RIOReceive>(rio.RIOReceive);
                rioFunctions.Send = Marshal.GetDelegateForFunctionPointer<RIOSend>(rio.RIOSend);

                rioFunctions.CloseCompletionQueue = Marshal.GetDelegateForFunctionPointer<RIOCloseCompletionQueue>(rio.RIOCloseCompletionQueue);
                rioFunctions.DeregisterBuffer = Marshal.GetDelegateForFunctionPointer<RIODeregisterBuffer>(rio.RIODeregisterBuffer);
                rioFunctions.ResizeCompletionQueue = Marshal.GetDelegateForFunctionPointer<RIOResizeCompletionQueue>(rio.RIOResizeCompletionQueue);
                rioFunctions.ResizeRequestQueue = Marshal.GetDelegateForFunctionPointer<RIOResizeRequestQueue>(rio.RIOResizeRequestQueue);

                return rioFunctions;
            }
        }