Пример #1
0
        /// <summary>
        /// 서버에게 패킷을 보냅니다.
        /// 보내는 작업이 이미 동작중이면 작업큐에 메세지를 하나 더 얹습니다.
        /// </summary>
        /// <param name="packet">보내고자 하는 패킷입니다.</param>
        /// <param name="waitForThis">동기적으로 기다릴 것인지 결정하는 인자입니다.
        /// 기본값은 false 입니다.</param>
        /// 메세지를 보내라고 명령하는 함수. 이 함수는 위의 두 함수와 결합하여 사용한다.
        public static void SendToServer(byte[] packet, bool waitForThis = false)
        {
            ConnectInfo ci = ConnectInfo.getInstance();

            ci.sendMsgQueue.Enqueue(packet);

            if (ci.sendTask == null)
            {
                ci.sendTask = new Task(StartSendingQueue);
                if (waitForThis)
                {
                    ci.sendTask.RunSynchronously();
                }
                else
                {
                    ci.sendTask.Start();
                }
            }
            else if (ci.sendTask.IsCompleted)
            {
                ci.sendTask = new Task(StartSendingQueue);
                if (waitForThis)
                {
                    ci.sendTask.RunSynchronously();
                }
                else
                {
                    ci.sendTask.Start();
                }
            }
            else if (waitForThis)
            {
                ci.sendTask.Wait();
            }
        }
Пример #2
0
        ///////////////////////////// 이벤트 영역 /////////////////////////////

        private void MainFrame_Load(object sender, EventArgs e)
        {
            ci = ConnectInfo.getInstance();
            ci.tcpClient.Client.BeginReceive(ci.recvHeaderBuffer, ci.recvHeaderReaded, CustomProtocolManager.HEADER_SIZE, 0, MessageHandler.MainFrameMessageReceiveCallback, ci);

            if (!ChangeChannel()) // 처음에 채널 선택은 무조건 해야한다.
            {
                Application.Exit();
                this.Close();
                return;
            }

            timer_UserListRefresh.Start();
        }
Пример #3
0
        // 확인시 로직
        private void Confirm()
        {
            if (btn_JoinNameCheck.Enabled == true)
            {
                MessageBox.Show("ID 중복 여부를 확인해주십시오.", "절차 안내", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                return;
            }

            if (btn_JoinNicknameCheck.Enabled == true)
            {
                MessageBox.Show("Nickname 중복 여부를 확인해주십시오.", "절차 안내", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                return;
            }

            JoinData data = new JoinData()
            {
                user_id       = txt_JoinName.Text,
                user_password = txt_JoinPassword.Text,
                user_email    = txt_JoinEmail.Text,
                nickname      = txt_JoinNickname.Text,
                user_gender   = rb_JoinWoman.Checked
            };

            if (!MessageHandler.MakeAccount(data))
            {
                if (!ConnectInfo.getInstance().tcpClient.Client.Connected)
                {
                    MessageBox.Show("서버와 연결이 끊어졌습니다. 연결상태를 확인하십시오.\n연결상태에 문제가 없다면 서버가 오프라인이 되었을 가능성이 있습니다."
                                    , "연결 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Application.Exit();
                    return;
                }

                MessageBox.Show("계정을 생성하지 못했습니다. \n절차상에 문제가 생겼거나 누군가가 먼저 ID나 닉네임을 선점했을 가능성이 있습니다.", "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            MessageBox.Show("계정 생성에 성공하였습니다. 생성하신 계정으로 로그인해주십시오!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);

            id  = txt_JoinName.Text;
            pwd = txt_JoinPassword.Text;

            DialogResult = DialogResult.OK;
            this.Close();
        }
Пример #4
0
        /// <summary>
        /// 로그인을 시도하고 결과를 반환합니다.
        /// </summary>
        /// <param name="token">로그인에 사용할 토큰을 의미합니다.</param>
        /// <returns>로그인 결과를 의미합니다.</returns>
        public static bool TryLogin(CustomProtocolManager.LoginToken token)
        {
            ConnectInfo ci = ConnectInfo.getInstance();

            SendToServer(CustomProtocolManager.MakeLoginPacket(token, ci.securityParameter), true);
            int index          = 0;
            int requiredLength = CustomProtocolManager.HEADER_SIZE + 1;

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

            if (CustomProtocolManager.ParseResponsePacket(recvData, CustomProtocolManager.HEADER_SIZE)
                == CustomProtocolManager.GenericResponseType.Acknowledge)
            {
                return(true);
            }
            return(false);
        }
Пример #5
0
        /// <summary>
        /// 계정을 만들어달라고 요청합니다. 성공 여부가 반환됩니다.
        /// </summary>
        /// <param name="data">계정 양식입니다.</param>
        /// <returns>성공 여부</returns>
        public static bool MakeAccount(JoinData data)
        {
            ConnectInfo ci = ConnectInfo.getInstance();

            SendToServer(CustomProtocolManager.MakeJoinPacket(data), true);
            int index          = 0;
            int requiredLength = CustomProtocolManager.HEADER_SIZE + 1;

            byte[] recvData = new byte[requiredLength];

            if (!ReceiveFunction(ci.tcpClient.Client, ref recvData, ref index, requiredLength))
            {
                return(false);
            }

            if (CustomProtocolManager.ParseResponsePacket(recvData, CustomProtocolManager.HEADER_SIZE)
                == CustomProtocolManager.GenericResponseType.Acknowledge)
            {
                return(true);
            }
            return(false);
        }
Пример #6
0
        /// <summary>
        /// 회원가입시 데이터가 중복되었는지 개별적으로 확인할때 사용하는 함수입니다.
        /// 형식과 데이터를 받아서 중복 여부를 확인합니다. True일 경우 사용해도 좋다는 의미입니다.
        /// </summary>
        /// <param name="type">확인할 데이터의 타입입니다.</param>
        /// <param name="context">확인할 데이터의 내용입니다.</param>
        /// <returns>사용 가능 여부</returns>
        public static bool CheckDuplicateData(CustomProtocolManager.DuplicateCheckJoinType type, string context)
        {
            ConnectInfo ci = ConnectInfo.getInstance();

            SendToServer(CustomProtocolManager.MakeDuplicateCheckForJoin(type, context), true);
            int index          = 0;
            int requiredLength = CustomProtocolManager.HEADER_SIZE + 1;

            byte[] recvData = new byte[requiredLength];

            if (!ReceiveFunction(ci.tcpClient.Client, ref recvData, ref index, requiredLength))
            {
                return(false);
            }

            if (CustomProtocolManager.ParseResponsePacket(recvData, CustomProtocolManager.HEADER_SIZE)
                == CustomProtocolManager.GenericResponseType.Acknowledge)
            {
                return(true);
            }
            return(false);
        }
Пример #7
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 { }
        }
Пример #8
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);
        }
Пример #9
0
 public ConnectForm()
 {
     InitializeComponent();
     ci = ConnectInfo.getInstance();
 }
Пример #10
0
 public LoginForm()
 {
     InitializeComponent();
     ci = ConnectInfo.getInstance();
     txt_ServerName.Text = ci.ServerName;
 }