public static IObservable<Socket> ToConnectObservable(this IPEndPoint endpoint, Selector selector, CancellationToken token)
        {
            return Observable.Create<Socket>(observer =>
            {
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { Blocking = false };

                Exception error = null;
                bool isConnected = false;

                try
                {
                    socket.Connect(endpoint);
                    isConnected = true;
                }
                catch (Exception exception)
                {
                    if (!exception.IsWouldBlock())
                        error = exception;
                }
                if (!isConnected && error == null)
                {
                    var waitEvent = new ManualResetEvent(false);
                    var waitHandles = new[] {token.WaitHandle, waitEvent};

                    selector.AddCallback(SelectMode.SelectWrite, socket,
                        _ =>
                        {
                            try
                            {
                                if (!socket.Connected)
                                    socket.Connect(endpoint);
                                selector.RemoveCallback(SelectMode.SelectWrite, socket);
                                isConnected = true;
                                waitEvent.Set();
                            }
                            catch (Exception exception)
                            {
                                if (exception.IsWouldBlock())
                                    return;
                                error = exception;
                                waitEvent.Set();
                            }
                        });

                    if (WaitHandle.WaitAny(waitHandles) == 0)
                        token.ThrowIfCancellationRequested();
                }

                if (error == null)
                    observer.OnNext(socket);
                else
                    observer.OnError(error);

                observer.OnCompleted();

                return Disposable.Empty;
            });
        }
        public static IObservable<Socket> ToListenerObservable(this Socket socket, int backlog, Selector selector)
        {
            return Observable.Create<Socket>(observer =>
            {
                socket.Listen(backlog);

                selector.AddCallback(SelectMode.SelectRead, socket, _ =>
                {
                    var accepted = socket.Accept();
                    accepted.Blocking = false;
                    observer.OnNext(accepted);
                });

                return Disposable.Create(() => selector.RemoveCallback(SelectMode.SelectRead, socket));
            });
        }
Example #3
0
        static void Main(string[] args)
        {
            var endpoint = ProgramArgs.Parse(args, new[] { "127.0.0.1:9211" }).EndPoint;

            var cts = new CancellationTokenSource();
            var bufferManager = BufferManager.CreateBufferManager(2 << 16, 2 << 8);

            var selector = new Selector();
            Task.Factory.StartNew(() => selector.Dispatch(60000000, cts.Token), cts.Token);

            endpoint.ToConnectObservable(selector, cts.Token)
                .Subscribe(socket =>
                {
                    var frameClientSubject = socket.ToFrameClientSubject(SocketFlags.None, bufferManager, selector, cts.Token);

                    var observerDisposable =
                        frameClientSubject
                            .ObserveOn(TaskPoolScheduler.Default)
                            .Subscribe(
                                disposableBuffer =>
                                {
                                    Console.WriteLine("Read: " + Encoding.UTF8.GetString(disposableBuffer.Bytes, 0, disposableBuffer.Length));
                                    disposableBuffer.Dispose();
                                },
                                error => Console.WriteLine("Error: " + error.Message),
                                () => Console.WriteLine("OnCompleted: FrameReceiver"));

                    Console.In.ToLineObservable()
                        .Subscribe(
                            line =>
                            {
                                var writeBuffer = Encoding.UTF8.GetBytes(line);
                                frameClientSubject.OnNext(new DisposableByteBuffer(writeBuffer, writeBuffer.Length, Disposable.Empty));
                            },
                            error => Console.WriteLine("Error: " + error.Message),
                            () => Console.WriteLine("OnCompleted: LineReader"));

                    observerDisposable.Dispose();

                    cts.Cancel();
                });

            cts.Token.WaitHandle.WaitOne();
        }
Example #4
0
        static void Main(string[] args)
        {
            var endpoint = ProgramArgs.Parse(args, new[] { "127.0.0.1:9211" }).EndPoint;

            var cts = new CancellationTokenSource();
            var selector = new Selector();

            endpoint.ToListenerObservable(10, selector)
                .ObserveOn(TaskPoolScheduler.Default)
                .Subscribe(
                    client =>
                        client.ToClientObservable(1024, SocketFlags.None, selector)
                            .Subscribe(client.ToClientObserver(SocketFlags.None, selector, cts.Token), cts.Token),
                    error => Console.WriteLine("Error: " + error.Message),
                    () => Console.WriteLine("OnCompleted"),
                    cts.Token);

            Task.Factory.StartNew(() => selector.Dispatch(60000000, cts.Token), cts.Token);

            Console.WriteLine("Press <ENTER> to quit");
            Console.ReadLine();

            cts.Cancel();
        }
        public static IObservable<DisposableByteBuffer> ToFrameClientObservable(this Socket socket, SocketFlags socketFlags, BufferManager bufferManager, Selector selector)
        {
            return Observable.Create<DisposableByteBuffer>(observer =>
            {
                var headerState = new BufferState(new byte[sizeof(int)], 0, sizeof(int));
                var contentState = new BufferState(null, 0, -1);

                var selectMode = socketFlags.HasFlag(SocketFlags.OutOfBand) ? SelectMode.SelectError : SelectMode.SelectRead;

                selector.AddCallback(selectMode, socket, _ =>
                {
                    try
                    {
                        if (headerState.Length > 0)
                        {
                            headerState.Advance(socket.Receive(headerState.Bytes, headerState.Offset, headerState.Length, socketFlags));

                            if (headerState.Length == 0)
                            {
                                contentState.Length = BitConverter.ToInt32(headerState.Bytes, 0);
                                contentState.Offset = 0;
                                contentState.Bytes = bufferManager.TakeBuffer(contentState.Length);
                            }
                        }

                        if (contentState.Bytes != null)
                        {
                            contentState.Advance(socket.Receive(contentState.Bytes, contentState.Offset, contentState.Length, socketFlags));

                            if (contentState.Length == 0)
                            {
                                var managedBuffer = contentState.Bytes;
                                var length = contentState.Offset;
                                observer.OnNext(new DisposableByteBuffer(managedBuffer, length, Disposable.Create(() => bufferManager.ReturnBuffer(managedBuffer))));

                                contentState.Bytes = null;

                                headerState.Length = headerState.Offset;
                                headerState.Offset = 0;
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        if (!exception.IsWouldBlock())
                            observer.OnError(exception);
                    }
                });

                return Disposable.Create(() => selector.RemoveCallback(SelectMode.SelectRead, socket));
            });
        }
        public static IObserver<DisposableByteBuffer> ToFrameClientObserver(this Socket socket, SocketFlags socketFlags, Selector selector, CancellationToken token)
        {
            return Observer.Create<DisposableByteBuffer>(disposableBuffer =>
            {
                var header = BitConverter.GetBytes(disposableBuffer.Length);
                var headerState = new BufferState(header, 0, header.Length);
                var contentState = new BufferState(disposableBuffer.Bytes, 0, disposableBuffer.Length);

                try
                {
                    headerState.Advance(socket.Send(headerState.Bytes, headerState.Offset, headerState.Length, socketFlags));

                    if (headerState.Length == 0)
                        contentState.Advance(socket.Send(contentState.Bytes, contentState.Offset, contentState.Length, socketFlags));

                    if (contentState.Length == 0)
                        return;
                }
                catch (Exception exception)
                {
                    if (!exception.IsWouldBlock())
                        throw;
                }

                var waitEvent = new AutoResetEvent(false);
                var waitHandles = new[] { token.WaitHandle, waitEvent };
                Exception error = null;

                selector.AddCallback(SelectMode.SelectWrite, socket,
                    _ =>
                    {
                        try
                        {
                            if (headerState.Length > 0)
                                headerState.Advance(socket.Send(headerState.Bytes, headerState.Offset, headerState.Length, socketFlags));

                            if (headerState.Length == 0)
                                contentState.Advance(socket.Send(contentState.Bytes, contentState.Offset, contentState.Length, socketFlags));

                            if (contentState.Length == 0)
                            {
                                selector.RemoveCallback(SelectMode.SelectWrite, socket);
                                waitEvent.Set();
                            }
                        }
                        catch (Exception exception)
                        {
                            if (exception.IsWouldBlock())
                                return;

                            error = exception;
                            selector.RemoveCallback(SelectMode.SelectWrite, socket);
                            waitEvent.Set();
                        }
                    });

                while (headerState.Length > 0 && contentState.Length > 0)
                {
                    if (WaitHandle.WaitAny(waitHandles) == 0)
                        token.ThrowIfCancellationRequested();

                    if (error != null)
                        throw error;
                }

                disposableBuffer.Dispose();
            });
        }
 public static ISubject<DisposableByteBuffer, DisposableByteBuffer> ToFrameClientSubject(this Socket socket, SocketFlags socketFlags, BufferManager bufferManager, Selector selector, CancellationToken token)
 {
     return Subject.Create(socket.ToFrameClientObserver(socketFlags, selector, token), socket.ToFrameClientObservable(socketFlags, bufferManager, selector));
 }
 public static IObservable<Socket> ToListenerObservable(this IPEndPoint endpoint, int backlog, Selector selector)
 {
     var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { Blocking = true };
     socket.Bind(endpoint);
     return socket.ToListenerObservable(backlog, selector);
 }