Example #1
0
        /// <summary>
        /// 송신을 시작하라고 명령하는 함수입니다.
        /// 현재 송신 기능은 보내야할 메세지를 작업형태로 만들고 '공존 큐'에 넣어서 관리하고 있기 때문에 사용합니다.
        /// 이 함수는 내부 로직에 의해 동기적으로 송신하므로 Task와 조합하여 사용해야합니다.
        /// </summary>
        private async static void StartSendingQueue()
        {
            byte[]      currentMessage;
            ConnectInfo ci = ConnectInfo.getInstance();

            try // 작업을 진행하는 서버가 접속종료를 해서 오류가 날 경우가 있다.
                // 그리고 다른 함수 절차에 따라 프로그램이 종료되려고 할때 이 정보가 말소 될 가능성이 있다.
                // 이때 말소된 정보에 접근하려하면 프로그램이 죽을 것이다. 이를 방지한다.
            {
                do
                {
                    if (!ci.sendMsgQueue.TryDequeue(out currentMessage))
                    {   // 꺼내오는데 실패하면 대기하고 재시도하게 한다.
                        await Task.Delay(ClientInfo.getInstance().sleepTime);

                        continue;
                    }

                    SendingFunction(ci.tcpClient.Client, currentMessage);
                } while (ci.sendMsgQueue.Count > 0);
            }
            catch { }
        }
Example #2
0
        /// <summary>
        /// 서버명을 요청한 후 수신받아 기록합니다. 절차는 동기식으로 작동합니다.
        /// 이 함수를 사용하면 인증 가능한 상태라고 초기화 되기 때문에,
        /// 처음 접속시가 아니면 사용하지 마십시오.
        /// </summary>
        /// <returns>성공 여부를 나타냅니다.</returns>
        public static bool ReceiveDefaultInfo()
        {
            string serverName;

            System.Security.Cryptography.RSAParameters parameters;
            int index = 0;

            byte[]          data;
            List <GameInfo> reqInfos;
            ConnectInfo     ci    = ConnectInfo.getInstance();
            ClientInfo      cInfo = ClientInfo.getInstance();

            data = CustomProtocolManager.MakeConnectRequestPacket();
            if (!SendingFunction(ci.tcpClient.Client, data))
            {
                return(false);
            }

            // 헤더 수신
            index = 0;
            data  = new byte[CustomProtocolManager.HEADER_SIZE];
            if (!ReceiveFunction(ci.tcpClient.Client, ref data, ref index, CustomProtocolManager.HEADER_SIZE))
            {
                return(false);
            }

            // 수신된 헤더 확인
            CustomProtocolManager.Header header = CustomProtocolManager.ParseHeader(ref data);

            // 데이터 수신
            index = 0;
            data  = new byte[header.size];
            if (!ReceiveFunction(ci.tcpClient.Client, ref data, ref index, (int)header.size))
            {
                return(false);
            }


            CustomProtocolManager.ParseClientReqInfoPacket(data, 0, (UInt32)data.Length, out serverName, out parameters, out reqInfos);
            ci.ServerName        = serverName;
            ci.securityParameter = parameters;

            // 필요 게임들이 존재하는지 확인


            DirectoryInfo di = new DirectoryInfo(ClientInfo.GAMEDATA_PATH);
            FileStream    fs;
            XmlSerializer xs = new XmlSerializer(typeof(GameInfo));
            GameInfo      registry;

            foreach (DirectoryInfo sdi in di.GetDirectories())
            {
                foreach (FileInfo fi in sdi.GetFiles())
                {
                    if (!fi.Extension.Equals(".info"))
                    {
                        continue;
                    }

                    fs = fi.OpenRead();

                    registry = (GameInfo)xs.Deserialize(fs);

                    for (int i = 0; i < reqInfos.Count; ++i)
                    {
                        if (GameInfo.IsSameInfo(reqInfos[i], registry))
                        {
                            cInfo.gameRegistries.Add(new GameRegistry {
                                gameInfo = registry, folderPath = fi.DirectoryName
                            });
                            reqInfos.RemoveAt(i);
                        }
                    }

                    fs.Close();
                }
            }

            // 필요 정보가 남아있으면 필요한 게임이 없으므로 서버 이용 불가
            if (reqInfos.Count != 0)
            {
                string msg;

                foreach (GameInfo gi in reqInfos)
                {
                    msg = "이 서버에 접속하기 위해서는 다음의 게임이 필요합니다."
                          + "\n게임명: " + gi.name
                          + "\n버전: " + gi.gameVersion
                          + "\n제작자: " + gi.producer;

                    MessageBox.Show(msg, "파일 누락");
                }
                return(false);
            }

            return(true);
        }
 public ConnectForm()
 {
     InitializeComponent();
     ci = ConnectInfo.getInstance();
 }
Example #4
0
        /// <summary>
        /// 비동기 수신 메서드로부터 반응이오면 실행되는 콜백 함수입니다.
        /// 해당 콜백 함수는 MainFrame에서 사용되어야 합니다.
        /// </summary>
        /// <param name="ar">송신정보를 담아 생성되는 인터페이스 객체입니다.</param>
        public static void MainFrameMessageReceiveCallback(IAsyncResult ar)
        {
            #region 메세지 수신
            ConnectInfo ci = (ConnectInfo)ar.AsyncState;
            CustomProtocolManager.Header header;
            byte[] receivedData;

            try
            {
                ci.recvHeaderReaded += ci.tcpClient.Client.EndReceive(ar);

                if (ci.tcpClient.Connected == false)
                {
                    throw new Exception();                                   // 연결이 끊기면 메세지를 버리라고 알림
                }
                if (ci.recvHeaderReaded < CustomProtocolManager.HEADER_SIZE) // 메세지가 헤더의 원본 크기만큼 안왔다면 비동기적으로 더 수신하라고 명령한다
                {
                    ci.tcpClient.Client.BeginReceive(ci.recvHeaderBuffer, ci.recvHeaderReaded, CustomProtocolManager.HEADER_SIZE - ci.recvHeaderReaded,
                                                     0, MainFrameMessageReceiveCallback, ci);
                    return;
                }

                // 헤더의 원본 크기만큼 읽었거나 그 이상 읽은경우는 이 구역을 실행한다.
                header = CustomProtocolManager.ParseHeader(ref ci.recvHeaderBuffer);

                int received = 0;
                receivedData = new byte[header.size];

                if (!ReceiveFunction(ci.tcpClient.Client, ref receivedData, ref received, (int)header.size))
                {
                    throw new Exception();// 동기 수신에 실패하면 연결에 문제가 있으므로 예외처리
                }
                // 서버랑 다르게 처리하기 전에 비동기 수신 이벤트를 새로 등록한다.
                ci.recvHeaderReaded = 0; // 인덱스 초기화
            }
            catch (Exception e)
            { // 동작에 오류가 있었다면 통신에 문제가 있는 것이므로 프로그램을 재시작한다.
                Console.WriteLine("MainFrameMessageReceiveCallback: " + e.Message);

                MessageBox.Show("서버와의 통신에 이상이 생겨 접속이 끊겼습니다." +
                                "\n본 시스템의 네트워크에 이상이 없다면 " +
                                "서버가 오프라인이 되었을 가능성이 높습니다.", "통신 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);

                Application.Exit();
                return;
            }
            #endregion
            #region 메세지 처리
            switch (header.typeNumber)
            {
            case CustomProtocolManager.TypeNumber.Chatting:
                ChattingHandleFunction(header, receivedData);
                break;

            case CustomProtocolManager.TypeNumber.ServerMessage:
                ServerMessageHandleFunction(receivedData);
                break;

            case CustomProtocolManager.TypeNumber.InfoReq:
                InfoTypeMsgHandleFunction(header, receivedData);
                break;

            case CustomProtocolManager.TypeNumber.InfoChange:
                InfoChangeMsgHandleFunction(header, receivedData);
                break;

            // 미사용 메세지 처리 구간
            case CustomProtocolManager.TypeNumber.MakeConnection: // 기초정보 제공은 앞선 폼에서 모두 사용한다
            case CustomProtocolManager.TypeNumber.Authorization:  // 인증방식은 로그인과 회원가입에서 모두 처리하는 방식이다
            default: break;                                       // 어느쪽에도 속하지 않으면 메세지를 버림
            }

            #endregion

            try
            {
                ci.tcpClient.Client.BeginReceive(ci.recvHeaderBuffer, 0, CustomProtocolManager.HEADER_SIZE, 0, MainFrameMessageReceiveCallback, ci);
            }
            catch (Exception e)
            {
                Console.WriteLine("MainFrameMessageReceiveCallback: " + e.Message);

                MessageBox.Show("서버와의 통신에 이상이 생겨 접속이 끊겼습니다." +
                                "\n본 시스템의 네트워크에 이상이 없다면 " +
                                "서버가 오프라인이 되었을 가능성이 높습니다.", "통신 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);

                Application.Exit();
                return;
            }
        }
Example #5
0
 public LoginForm()
 {
     InitializeComponent();
     ci = ConnectInfo.getInstance();
     txt_ServerName.Text = ci.ServerName;
 }