Пример #1
0
        public void OnConnected(Socket tcpSocket)
        {
            _ = tcpSocket ?? throw new ArgumentNullException(nameof(tcpSocket));
            if (tcpSocket.Connected == false)
            {
                throw new ArgumentException(nameof(tcpSocket));
            }

            m_Connection = new AsyncTcpConnection(tcpSocket);
            m_Connection.Subscribe(
                onReceived: HandleReceivedData,
                onError: error =>
            {
                Log.I.Error($"패킷 송신 중 오류 발생", error);
                Dispose();
            },
                onReceiveCompleted: () => Dispose());
            m_PacketProcessor = new SCPacketProcessor(this);
            m_PacketSender    = new CSPacketSender(m_Connection);
        }
        public ClientConnection(long id, Socket tcpSocket, SessionManager sessionManager)
        {
            _ = tcpSocket ?? throw new ArgumentNullException(nameof(tcpSocket));
            if (tcpSocket.Connected == false)
            {
                throw new ArgumentException(nameof(tcpSocket));
            }

            Id           = id;
            m_Connection = new AsyncTcpConnection(tcpSocket);
            m_Connection.Subscribe(
                onReceived: HandleReceivedData,
                onError: error =>
            {
                Log.I.Error($"패킷 송신 중 오류 발생", error);
                Dispose();
            },
                onReceiveCompleted: () => Dispose());

            var packeHandler = new CSPacketHandler(this, sessionManager);

            m_PacketProcessor = new CSPacketProcessor(packeHandler);
            m_PacketSender    = new SCPacketSender(m_Connection);
        }
Пример #3
0
        private static async Task PrepareSendRecvTcpStream(
            IPAddress ip,
            int port,
            int numberOfConnections,
            ConcurrentDictionary <long, AsyncTcpConnection> csStreams,
            ConcurrentDictionary <long, AsyncTcpConnection> scStreams,
            ConcurrentDictionary <long, BufferBlock <string> > csRecvQueues,
            ConcurrentDictionary <long, BufferBlock <string> > scRecvQueues)
        {
            for (long i = 0; i < numberOfConnections; i++)
            {
                csRecvQueues.TryAdd(i, new BufferBlock <string>(new DataflowBlockOptions {
                    BoundedCapacity = DataflowBlockOptions.Unbounded
                }));
                scRecvQueues.TryAdd(i, new BufferBlock <string>(new DataflowBlockOptions {
                    BoundedCapacity = DataflowBlockOptions.Unbounded
                }));
            }

            var csIds = new IdGenerator(0);
            var scIds = new IdGenerator(0);

            var acceptor = new AsyncTcpAcceptor(
                onNewConnection: (socket) =>
            {
                long scId         = scIds.Generate();
                var newConnection = new AsyncTcpConnection(socket);
                scStreams.TryAdd(scId, newConnection);

                Action onClosed = () =>
                {
                    scRecvQueues.TryGetValue(scId, out var scRecvQueue);
                    Assert.AreEqual(scRecvQueue.Count, 0);
                    Assert.IsTrue(scStreams.TryRemove(scId, out var temp));
                };

                newConnection.Subscribe(
                    onReceived: tcpData =>
                {
                    int parsedBytes = UnpackMessages(tcpData, out var messages);
                    scRecvQueues.TryGetValue(scId, out var scRecvQueue);
                    foreach (var message in messages)
                    {
                        scRecvQueue.Post(message);
                    }
                    return(parsedBytes);
                },
                    onError: error => Assert.Fail("AsyncTcpAcceptor 오류"),
                    onReceiveCompleted: onClosed);
            });

            acceptor.Bind(ip, port);
            acceptor.ListenAndStart(5);

            for (int i = 0; i < numberOfConnections; i++)
            {
                var timeout = new Queue <TimeSpan>(new[] { TimeSpan.FromMilliseconds(5000) });
                AsyncTcpConnector.Connect(
                    ip: ip,
                    port: port,
                    leftTimeoutList: timeout,
                    onCompleted: (bool isConnected, Socket socket) =>
                {
                    Assert.IsTrue(isConnected);

                    var csId          = csIds.Generate();
                    var newConnection = new AsyncTcpConnection(socket);
                    Assert.IsTrue(csStreams.TryAdd(csId, newConnection));

                    Action onClosed = () =>
                    {
                        csRecvQueues.TryGetValue(csId, out var csRecvQueue);
                        Assert.AreEqual(csRecvQueue.Count, 0);
                        Assert.IsTrue(csStreams.TryRemove(csId, out var temp));
                    };

                    newConnection.Subscribe(
                        onReceived: tcpData =>
                    {
                        int parsedBytes = UnpackMessages(tcpData, out var messages);
                        csRecvQueues.TryGetValue(csId, out var csRecvQueue);
                        foreach (var message in messages)
                        {
                            csRecvQueue.Post(message);
                        }
                        return(parsedBytes);
                    },
                        onError: error => onClosed(),
                        onReceiveCompleted: onClosed);
                });
            }

            while (csStreams.Count() < numberOfConnections ||
                   scStreams.Count() < numberOfConnections)
            {
                await Task.Delay(0);
            }

            acceptor.Dispose();
        }
Пример #4
0
        public void AsyncTcpAcceptor()
        {
            var listenIp   = IPAddress.Loopback;
            int listenPort = 12255;

            var acceptedConnections = new ConcurrentQueue <AsyncTcpConnection>();

            var acceptor = new AsyncTcpAcceptor(
                onNewConnection: accepted =>
            {
                var newConnection = new AsyncTcpConnection(accepted);
                newConnection.Subscribe(_ => 0, _ => { }, () => { });
                acceptedConnections.Enqueue(newConnection);
            });

            int numberOfBacklogSockets = 8;

            acceptor.Bind(listenIp, listenPort);
            acceptor.ListenAndStart(numberOfBacklogSockets);

            var isDone = new AutoResetEvent(false);

            Func <Socket, AsyncTcpConnection> tcpStreamCreator = socket =>
            {
                var newStream = new AsyncTcpConnection(socket);
                newStream.Subscribe(_ => 0, _ => { }, () => { });
                return(newStream);
            };

            AsyncTcpConnector.Connect(
                ip: listenIp,
                port: listenPort,
                leftTimeoutList: new Queue <TimeSpan>(new[]
            {
                TimeSpan.FromMilliseconds(100),
                TimeSpan.FromMilliseconds(100),
                TimeSpan.FromMilliseconds(100),
                TimeSpan.FromMilliseconds(100)
            }),
                onCompleted: (isConnected, socket) =>
            {
                Assert.IsTrue(isConnected);
                Assert.IsNotNull(socket);

                var newStream = tcpStreamCreator(socket);
                Assert.IsNotNull(newStream);

                isDone.Set();
            });

            Assert.IsTrue(isDone.WaitOne(TimeSpan.FromSeconds(5)));
            isDone.Reset();

            BecomeTrue(() =>
            {
                return(acceptedConnections.Count >= 1);
            }, TimeSpan.FromSeconds(1)).Wait();

            var connectionCount = 5 * numberOfBacklogSockets;

            for (int i = 0; i < connectionCount; i++)
            {
                AsyncTcpConnector.Connect(
                    ip: listenIp,
                    port: listenPort,
                    leftTimeoutList: new Queue <TimeSpan>(new[]
                {
                    TimeSpan.FromMilliseconds(100),
                    TimeSpan.FromMilliseconds(100),
                    TimeSpan.FromMilliseconds(100),
                    TimeSpan.FromMilliseconds(100)
                }),
                    onCompleted: (isConnected, socket) =>
                {
                    Assert.IsTrue(isConnected);
                    Assert.IsNotNull(socket);

                    var newStream = tcpStreamCreator(socket);
                    Assert.IsNotNull(newStream);

                    isDone.Set();
                });
            }

            BecomeTrue(() =>
            {
                return(acceptedConnections.Count >= connectionCount);
            }, TimeSpan.FromSeconds(1)).Wait();

            foreach (var c in acceptedConnections)
            {
                c.Dispose();
            }
        }
Пример #5
0
        public async Task ExceptionFromApplication()
        {
            // 어플리케이션 레벨에서 onReceiveTCPData()를 처리하면서 예외가 발생하는 경우,
            // 연결을 종료시켜 onTerminated가 불려야 한다. (좀비커넥션으로 남지 않도록)

            var ip   = IPAddress.Loopback;
            var port = 10000;

            AsyncTcpConnection clientSideConnection = null;
            AsyncTcpConnection serverSideConnection = null;

            bool isOppositeTerminated  = false;
            bool isExceptionTerminated = false;

            var acceptor = new AsyncTcpAcceptor(
                onNewConnection: (accepted) =>
            {
                serverSideConnection = new AsyncTcpConnection(
                    socket: accepted,
                    onSendError: exception => Log.I.Error("On Send Error", exception));
                serverSideConnection.Subscribe(
                    onReceived: data => UnpackMessages(data, out var _),
                    onError: error => Assert.Fail("실패"),
                    onReceiveCompleted: () => isOppositeTerminated = true);
            });

            acceptor.Bind(ip, port);
            acceptor.ListenAndStart(1);

            var timeout = new[] { TimeSpan.FromMilliseconds(5000), TimeSpan.FromMilliseconds(7000) };

            AsyncTcpConnector.Connect(
                ip: ip,
                port: port,
                leftTimeoutList: new Queue <TimeSpan>(timeout),
                onCompleted: (bool isConnected, Socket newSocket) =>
            {
                Assert.IsTrue(isConnected, "연결 실패");

                clientSideConnection = new AsyncTcpConnection(newSocket);
                clientSideConnection.Subscribe(
                    onReceived: data => throw new Exception("메세지 파싱"),
                    onError: error => isExceptionTerminated = true,
                    onReceiveCompleted: () => Assert.Fail("실패"));           //정상적으로 메세지 수신 시 테스트 실패
            });

            await TestHelper.BecomeTrue(() =>
            {
                return(clientSideConnection != null &&
                       serverSideConnection != null);
            }, TimeSpan.FromMilliseconds(3000));

            serverSideConnection.Send(new ArraySegment <byte>(Encoding.UTF8.GetBytes("핑퐁")));

            await TestHelper.BecomeTrue(() =>
            {
                return(isExceptionTerminated && isOppositeTerminated);
            }, TimeSpan.FromSeconds(2));

            Assert.IsTrue(isExceptionTerminated);
            Assert.IsTrue(isOppositeTerminated);

            acceptor.Dispose();

            clientSideConnection.Dispose();
            serverSideConnection.Dispose();
        }