Beispiel #1
0
        /// <summary>
        /// todo:검토중...
        /// 원격 서버에 접속 성공 했을 때 호출됩니다.
        /// </summary>
        /// <param name="socket"></param>
        public void on_connect_completed(Socket socket, CUserToken token)
        {
            // SocketAsyncEventArgsPool에서 빼오지 않고 그때 그때 할당해서 사용한다.
            // 풀은 서버에서 클라이언트와의 통신용으로만 쓰려고 만든것이기 때문이다.
            // 클라이언트 입장에서 서버와 통신을 할 때는 접속한 서버당 두개의 EventArgs만 있으면 되기 때문에 그냥 new해서 쓴다.
            // 서버간 연결에서도 마찬가지이다.
            // 풀링처리를 하려면 c->s로 가는 별도의 풀을 만들어서 써야 한다.
            SocketAsyncEventArgs receive_event_arg = new SocketAsyncEventArgs();

            receive_event_arg.Completed += new EventHandler <SocketAsyncEventArgs>(receive_completed);
            receive_event_arg.UserToken  = token;
            receive_event_arg.SetBuffer(new byte[1024], 0, 1024);

            SocketAsyncEventArgs send_event_arg = new SocketAsyncEventArgs();

            send_event_arg.Completed += new EventHandler <SocketAsyncEventArgs>(send_completed);
            send_event_arg.UserToken  = token;
            send_event_arg.SetBuffer(null, 0, 0);

            begin_receive(socket, receive_event_arg, send_event_arg);
        }
        void OnConnectAsync(object _sender, SocketAsyncEventArgs _connectArgs)
        {
            Console.WriteLine(this + " OnConnectAsync");
            if (_connectArgs.SocketError == SocketError.Success)
            {
                Console.WriteLine(" > Socket Connect Success > Connect completd!");
                CUserToken _token = new CUserToken();

                // 데이터 수신 준비.
                networkService.OnConnectCompleted(client, _token);
                if (onConnected != null)
                {
                    onConnected(_token);
                }
            }
            else
            {
                // failed.
                Console.WriteLine(string.Format("Failed to connect. {0}", _connectArgs.SocketError));
            }
        }
Beispiel #3
0
        void on_connect_completed(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                //Console.WriteLine("Connect completd!");
                CUserToken token = new CUserToken();

                // 데이터 수신 준비.
                this.network_service.on_connect_completed(this.client, token);

                if (this.connected_callback != null)
                {
                    this.connected_callback(token);
                }
            }
            else
            {
                // failed.
                Console.WriteLine(string.Format("Failed to connect. {0}", e.SocketError));
            }
        }
        // This method is invoked when an asynchronous receive operation completes.
        // If the remote host closed the connection, then the socket is closed.
        //
        private void process_receive(SocketAsyncEventArgs e)
        {
            // check if the remote host closed the connection
            CUserToken token = e.UserToken as CUserToken;

            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                token.on_receive(e.Buffer, e.Offset, e.BytesTransferred);

                bool pending = token.socket.ReceiveAsync(e);
                if (!pending)
                {
                    // Oh! stack overflow??
                    process_receive(e);
                }
            }
            else
            {
                Console.WriteLine(string.Format("error {0},  transferred {1}", e.SocketError, e.BytesTransferred));
                close_clientsocket(token);
            }
        }
        private void process_receive(SocketAsyncEventArgs e)
        {
            CUserToken token = e.UserToken as CUserToken;

            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                // 이후의 작업은 CUserToken에 맡긴다.
                token.on_receive(e.Buffer, e.Offset, e.BytesTransferred); // 패킷 덩어리 만듭니다.

                // 다음 메시지 수신을 위해서 다시 Rece_Async 매소드 호출
                bool pending = token.socket.ReceiveAsync(e);
                if (!pending)
                {
                    process_receive(e);
                }
            }
            else
            {
                Console.WriteLine(string.Format("error {0},  transferred {1}", e.SocketError, e.BytesTransferred));
                close_clientsocket(token);
            }
        }
        /// <summary>
        /// 새로운 클라이언트가 접속 성공 했을 때 호출됩니다.
        /// AcceptAsync의 콜백 매소드에서 호출되며 여러 스레드에서 동시에 호출될 수 있기 때문에 공유자원에 접근할 때는 주의해야 합니다.
        /// </summary>
        /// <param name="_clientSocket"></param>
        void OnAcceptProcess(Socket _clientSocket, object _token)
        {
            Console.WriteLine(this + " OnAcceptProcess(신규유저가 접속됨(콜백받음))\r\n > _newClientSocket:{0}\r\n > token:{1}", _clientSocket, _token);
            //todo:
            // peer list처리.

            Interlocked.Increment(ref this.connectedCount);
            //Interlocked 클래스는 int 형 값을 증가시키거나 감소시키는데 사용한다.
            //멀티 쓰레드 환경에서 하나의 int 형 전역 변수를 공유한다고 생각해보자.
            //이런 경우에 A 쓰레드와 B 쓰레드가 값을 동시에 읽어와서
            //B 쓰레드가 수정한 값을 저장하고,
            //A 쓰레드가 다시 수정한 값을 저장하게 되면
            //B 쓰레드의 변경사항을 잃어버리게 된다.

            Console.WriteLine("  > connectedCount:{0} ThreadID:{1} _newClientSocket.Handle:{2}",
                              this.connectedCount,
                              Thread.CurrentThread.ManagedThreadId,
                              _clientSocket.Handle);

            // 플에서 하나 꺼내와 사용한다.
            SocketAsyncEventArgs _argsReceive = this.receiveArgsPool.Pop();
            SocketAsyncEventArgs _argsSend    = this.sendArgsPool.Pop();
            CUserToken           _userToken   = null;

            Console.WriteLine("  > argsReceive, argsSend -> 스택에서 뺴서");

            if (this.onSessionCreated != null)
            {
                Console.WriteLine("   > 서버세션(UserToken) 리스트에 등록");
                _userToken = _argsReceive.UserToken as CUserToken;
                this.onSessionCreated(_userToken);
            }

            Console.WriteLine("  > 연결 : UserTokent(_newClientSocket, _argsReceive, _argsSend)");
            ReceiveWaitBegin(_clientSocket, _argsReceive, _argsSend);
            //user_token.start_keepalive();
        }
Beispiel #7
0
        /// <summary>
        /// AcceptAsync의 콜백 매소드
        /// </summary>
        /// <param name="_sender"></param>
        /// <param name="_acceptArgs">AcceptAsync 매소드 호출시 사용된 EventArgs</param>
        void OnAcceptCallback(object _sender, SocketAsyncEventArgs _acceptArgs)
        {
            Console.WriteLine(this + " OnAcceptAsync (신규유저접속시도)\r\n -> _sender:{0}\r\n -> _acceptArgs:{1}", _sender, _acceptArgs);
            if (_acceptArgs.SocketError == SocketError.Success)
            {
                Console.WriteLine("  -> NewClient Success");
                // 접속에 따른 OS가 받아온 Socket를 SocketAsynEvnetArgs에 실어서 보내줌.
                // 새로 생긴 소켓을 보관해 놓은뒤~
                Socket     _clientSocket = _acceptArgs.AcceptSocket;
                CUserToken _token        = _acceptArgs.UserToken as CUserToken;

                // 다음 연결을 받아들인다.
                this.autoResetEvent.Set();

                // 이 클래스에서는 accept까지의 역할만 수행하고 클라이언트의 접속 이후의 처리는
                // 외부로 넘기기 위해서 콜백 매소드를 호출해 주도록 합니다.
                // 이유는 소켓 처리부와 컨텐츠 구현부를 분리하기 위함입니다.
                // 컨텐츠 구현부분은 자주 바뀔 가능성이 있지만, 소켓 Accept부분은 상대적으로 변경이 적은 부분이기 때문에
                // 양쪽을 분리시켜주는것이 좋습니다.
                // 또한 클래스 설계 방침에 따라 Listen에 관련된 코드만 존재하도록 하기 위한 이유도 있습니다.
                if (this.onAcceptNewClient != null)
                {
                    this.onAcceptNewClient(_clientSocket, _token);
                }

                return;
            }
            else
            {
                Console.WriteLine("  -> NewClient Fail");
                //todo:Accept 실패 처리.
                //Console.WriteLine("Failed to accept client.");
            }

            // 다음 연결을 받아들인다.
            this.autoResetEvent.Set();
        }
Beispiel #8
0
        // This method is called whenever a receive or send operation is completed on a socket
        //
        // <param name="e">SocketAsyncEventArg associated with the completed send operation</param>
        void send_completed(object sender, SocketAsyncEventArgs e)
        {
            CUserToken token = e.UserToken as CUserToken;

            token.process_send(e);
        }
Beispiel #9
0
 public CHeartbeatSender(CUserToken server, uint interval)
 {
     this.server          = server;
     this.interval        = interval;
     this.timer_heartbeat = new Timer(this.on_timer, null, Timeout.Infinite, this.interval * 1000);
 }