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); }
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(); }
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(); } }
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(); }