Exemple #1
0
        /**
         * @brief
         * 연결요청이 완료되거나 데이터통신이 왔을 때 이 함수가 호출됨.
         *
         * @details
         * 연결요청에 대한 결과값에 따라 처리함. 데이터통신은 startreceive를 호출해줌.
         */
        void receiveComplete(object sender, SocketAsyncEventArgs e)
        {
            if (e.LastOperation == SocketAsyncOperation.Connect)
            {
                if (e.SocketError == SocketError.Success)
                {
                    ConoConnect connect = e.UserToken as ConoConnect;

                    connectModule.networkHandler.Connect(connect);

                    startReceive(connect);
                }
                else
                {
                    Console.WriteLine("Failed to connect with server.");

                    IConoNetworkHandler networkHandler = connectModule.networkHandler;

                    //ToDo. remove connectModule, clientConnector, connect

                    networkHandler.Connect(null);
                }
            }
            else
            {
                receiveData(null, e);
            }
        }
Exemple #2
0
        /**
         * @brief
         * 연결요청을 하는 함수.
         *
         * @details
         * 연결요청을 하고 연결요청의 결과값을 receiveComplete함수로 넘겨줌.
         */
        public void Connect()
        {
            ConoConnect connect = connectModule.CreateConnect(socket);

            if (connect == null)
            {
                Console.WriteLine("conoConnect");
                return;
            }

            connect.recvSocketAsyncEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(receiveComplete);

            bool pending = true;

            try
            {
                connect.recvSocketAsyncEventArgs.RemoteEndPoint = endpoint;
                pending = socket.ConnectAsync(connect.recvSocketAsyncEventArgs);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return;
            }


            if (!pending)
            {
                receiveComplete(null, connect.recvSocketAsyncEventArgs);
            }
        }
        /**
         * @brief
         * 연결 이후나 데이터를 한번 읽은 이후 이 함수를 호출해 다른 컴퓨터로부터 올 데이터를 기다린다고 설정함.
         *
         * @details
         * 비동기로 상대방의 정보를 기다림.\n
         *
         * @todo
         * stack overflow 발생 가능성 있음. check!
         */
        protected void startReceive(ConoConnect connect)
        {
            bool pending = connect.socket.ReceiveAsync(connect.recvSocketAsyncEventArgs);

            if (!pending)
            {
                receiveData(null, connect.recvSocketAsyncEventArgs);
            }
        }
        /**
         * @brief
         * ConoConnect를 생성
         */
        internal ConoConnect CreateConnect(Socket socket)
        {
            ConoConnect connect = new ConoConnect(0);

            if (connect.Init(socket, this) == false)
            {
                return(null);
            }

            return(connect);
        }
        /**
         * @brief
         * 상대방의 연결요청이 왔을 때 호출되는 함수
         *
         * @details
         * ConoConnect 객체를 만들고 데이터 받을 준비를 함.\n
         */
        void AcceptCompleted(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                Socket clientSocket = e.AcceptSocket;

                this.flowControlEvent.Set();

                ConoConnect connect = connectModule.CreateConnect(clientSocket);

                if (connect == null)
                {
                    Console.WriteLine("conoConnect");
                    return;
                }

                connect.recvSocketAsyncEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(receiveData);

                //bool pending = true;
                //try
                //{
                //	connect.recvSocketAsyncEventArgs.RemoteEndPoint = endpoint;
                //	pending = socket.ConnectAsync(connect.recvSocketAsyncEventArgs);
                //}
                //catch (Exception e)
                //{
                //	Console.WriteLine(e.Message);
                //	return;
                //}

                connectModule.networkHandler.Connect(connect);

                startReceive(connect);
            }
            else
            {
                Console.WriteLine("Failed to accept client.");
            }
        }
        /**
         * @brief
         * 데이터를 받았을 때 이 함수를 호출함.
         *
         * @details
         * 데이터가 짤려 오거나 여러개로 붙어오거나 하는 것들을 하나의 완전한 데이터로 만듬.\n
         * 첫 데이터의 4바이트는 데이터 크기를 나타냄.\n
         * 처리 이후에는 다시 startReceive를 호출해 다음 데이터를 기다림.
         */
        protected void receiveData(object sender, SocketAsyncEventArgs e)
        {
            ConoConnect connect = e.UserToken as ConoConnect;

            if (e.SocketError == SocketError.Success)
            {
                byte[] trimedData = connect.GetTrimedData();

                byte[] wholeByte = null;

                int wholeByteLen = 0;

                if (trimedData == null)                 //저장된 버퍼가 존재하지 않을 때
                {
                    wholeByte = e.Buffer;

                    wholeByteLen = e.BytesTransferred;
                }
                else //버퍼에 저장된 것이 있을 때
                {
                    wholeByte = new byte[e.BytesTransferred + trimedData.Length];

                    for (int i = 0; i < e.BytesTransferred + trimedData.Length; ++i)
                    {
                        wholeByte[i] = i < trimedData.Length ? trimedData[i] : e.Buffer[i - trimedData.Length];
                    }

                    wholeByteLen = wholeByte.Length;
                }

                while (true)
                {
                    if (e.BytesTransferred < 4)                     // 길이값을 나타내는 문자열보다 작은 양의 데이터가 왔을 때
                    {
                        connect.SetTrimedData(wholeByte, wholeByteLen);

                        break;
                    }

                    //첫 4바이트를 잘라서 데이터의 크기를 확인
                    byte[] bytes = new byte[4];

                    for (int i = 0; i < 4; i++)
                    {
                        bytes[i] = wholeByte[i];
                    }

                    int dataSize = BitConverter.ToInt32(bytes, 0);


                    int receivedDataSize = wholeByteLen - 4;


                    if (receivedDataSize == dataSize)                     // 날아온 데이터와 받아야 할 데이터의 크기가 일치할 때
                    {
                        byte[] data = new byte[receivedDataSize];

                        for (int i = 0; i < receivedDataSize; i++)
                        {
                            data[i] = wholeByte[i + 4];
                        }

                        Console.WriteLine("receive data - " + Encoding.Default.GetString(data, 0, dataSize));

                        connect.connectModule.networkHandler.ReceiveData(connect, data, dataSize);

                        connect.SetTrimedData(null, 0);


                        break;
                    }
                    else if (receivedDataSize < dataSize)                     // 날아온 데이터와 받아야 할 데이터의 크기보다 작을 때
                    {
                        connect.SetTrimedData(wholeByte, wholeByteLen);

                        break;
                    }
                    else                      // 날아온 데이터와 받아야 할 데이터의 크기보다 클 때(첫 완전한 데이터를 처리하고 다음 데이터로 다시 receiveData를 수행함)
                    {
                        byte[] firstData = new byte[dataSize];

                        for (int i = 0; i < dataSize; i++)
                        {
                            firstData[i] = wholeByte[i + 4];
                        }

                        byte[] secondData = new byte[receivedDataSize - dataSize];

                        for (int i = 0; i < receivedDataSize - dataSize; i++)
                        {
                            secondData[i] = wholeByte[i + dataSize + 4];
                        }

                        connect.SetTrimedData(secondData, secondData.Length);

                        Console.WriteLine("receive data - " + Encoding.Default.GetString(firstData, 0, dataSize));

                        connect.connectModule.networkHandler.ReceiveData(connect, firstData, dataSize);

                        wholeByte = new byte[secondData.Length];

                        for (int i = 0; i < secondData.Length; i++)
                        {
                            wholeByte[i] = secondData[i];
                        }

                        continue;
                    }
                }
            }
            else
            {
                Console.WriteLine("Failed to receive.");
            }

            startReceive(connect);             //다음 데이터를 기다림.
        }