Пример #1
0
        /* --소켓 데이터 송신 함수-- */
        static void SendCall(IAsyncResult iar)
        {
            // 강제로 Client 종료시 프로그램 사망을 방지하기 위하여 try catch문을 사용
            try
            {
                // 개별 핸들러(클라이언트)의 상태 인스턴스 받아오기
                BSstateBuffer state = (BSstateBuffer)iar.AsyncState;

                // 디버그 로그 콘솔에 출력
                Console.WriteLine(state.clientCounter + " 번 클라이언트로 데이터를 송신하는 중...\n");

                // 데이터 송신
                int sendSize = workingSocket[state.clientCounter].EndSend(iar);
                Console.WriteLine("보낸 데이터 크기 -> " + sendSize + "\n");

                // 송수신 함수 스레드 계속 진행하도록 허락해 계속 송수신 처리
                sendAllDone[state.clientCounter].Set();
            }
            catch (Exception exc)
            {
                Console.WriteLine("데이터 송신 실패...\n" + exc + "\n");
                return;
            }
        }
Пример #2
0
        public static byte[] sendBuffer = new byte[1024]; // 보낼 데이터 저장용 버퍼 정의


        /* --소켓 연결 함수-- */
        static void AcceptCall(IAsyncResult iar)
        {
            // 강제로 Client 종료시 프로그램 사망을 방지하기 위하여 try catch문을 사용
            try
            {
                Console.WriteLine("연결을 승인하는 중...\n");

                // 리스너(서버), 핸들러(클라이언트) 소켓 정의하고 연결 승인
                Socket listenerSocket = (Socket)iar.AsyncState;
                Socket handlerSocket  = listenerSocket.EndAccept(iar);

                // 개별 핸들러(클라이언트)의 상태 인스턴스 생성
                BSstateBuffer state = new BSstateBuffer();

                // 송수신 스레드 동기화 리스트 추가
                sendAllDone.Add(new ManualResetEvent(false));

                // 핸들러(클라이언트) 소켓을 추후 송수신에 사용을 위해 전역 변수를 리스트에 추가
                workingSocket.Add(handlerSocket);

                // 수신용 데이터 저장용 전역 변수를 리스트에 추가
                clientDataList.Add(new BSclientData());

                // 몇번째 클라이언트(리스트)인지 카운트 저장
                state.clientCounter = workingSocket.Count - 1;

                // 클라이언트 연결정보 표시
                string clientAddress = workingSocket[state.clientCounter].RemoteEndPoint.ToString(); // 클라이언트 IP, Port 가져오기 (예시 123.123.123.123:1234)
                Console.WriteLine(state.clientCounter + " 번 클라이언트 연결됨 -> " + clientAddress + "\n");

                // 메인 함수 스레드 계속 진행하도록 허락해 다음 클라이언트 연결 계속 받기
                serverAllDone.Set();

                // 클라이언트에 데이터 송수신 계속 시도
                while (true)
                {
                    // 클라이언트와 이미 송수신 중이기 때문에 송수신 함수 스레드 일시중지
                    sendAllDone[state.clientCounter].Reset();

                    // 데이터 수신 시작
                    workingSocket[state.clientCounter].BeginReceive(state.receiveBuffer, 0, state.receiveBuffer.Length, SocketFlags.None,
                                                                    new AsyncCallback(ReceiveCall), state);

                    // 여유 대기시간
                    Thread.Sleep(200);

                    // 클라이언트가 연결 종료 요청을 보낸경우 소켓 리스트 비우고 연결 스레드 종료
                    if (clientDataList[state.clientCounter].exitConnection == "T")
                    {
                        workingSocket.RemoveAt(state.clientCounter);  // 해당 클라이언트 번호의 소켓 데이터 제거
                        clientDataList.RemoveAt(state.clientCounter); // 해당 클라이언트 번호의 클라이언트 데이터 제거
                        break;
                    }

                    // 클라이언트와 이미 송수신 중인지 확인하고 송수신 함수 스레드 계속 진행
                    sendAllDone[state.clientCounter].WaitOne();
                }
            }
            catch (Exception exc) // 예외사항 발생시 연결 종료
            {
                Console.WriteLine("클라이언트와 연결 실패...\n" + exc);
                return;
            }
        }
Пример #3
0
        /* --소켓 데이터 수신 함수-- */
        static void ReceiveCall(IAsyncResult iar)
        {
            // 강제로 Client 종료시 프로그램 사망을 방지하기 위하여 try catch문을 사용
            try
            {
                // 개별 핸들러(클라이언트)의 상태 인스턴스 받아오기
                BSstateBuffer state = (BSstateBuffer)iar.AsyncState;

                // 디버그 로그 콘솔에 출력
                Console.WriteLine(state.clientCounter + " 번 클라이언트로 부터 데이터를 수신받는 중...\n");

                // 핸들러(클라이언트) 소켓을 통해 데이터 수신받고 사이즈 저장
                int receiveSize = workingSocket[state.clientCounter].EndReceive(iar);

                // 받을 데이터가 있는지 확인 (데이터 길이가 0보다 크면)
                if (receiveSize > 0)
                {
                    // 만약 마지막으로 받은 버퍼에서 EOF(문장의 끝)을 발견하지 못한 경우 데이터 계속 받음
                    if (state.receiveBuffer[state.receiveBuffer.Length - 1] != '\0')
                    {
                        // 데이터가 아직 다 수신되지 않았기 때문에 계속 호출하여 받아야함
                        workingSocket[state.clientCounter].BeginReceive(state.receiveBuffer, 0, state.receiveBuffer.Length, SocketFlags.None,
                                                                        new AsyncCallback(ReceiveCall), state);
                    }
                    else // 데이터가 다 수신되었음
                    {
                        // 버퍼의 내용을 수신 데이터 변수에 저장
                        state.receiveData = Encoding.UTF8.GetString(state.receiveBuffer, 0, receiveSize);
                        Console.WriteLine("받은 데이터 -> " + state.receiveData + "\n");

                        // 받은 메세지 | 단위로 잘라서 저장
                        // receiveData = "MAC address | Exit Connection? | Nick name | UFO position | UFO velocity | UFO rotation | Hitted UFO | My bullet position + Velocity + Remaining time..."
                        string[] receiveSplitData = state.receiveData.Split('|'); // 받은 데이터를 요소별로 잘라서 저장한 배열 정의
                        Console.WriteLine("자른 데이터는 ->\n");

                        // 자른 메세지 표시 & BSclientData 클래스 형태로 저장
                        for (int countRec = 0; countRec < receiveSplitData.Length; countRec++)
                        {
                            Console.WriteLine(receiveSplitData[countRec]);
                            switch (countRec)
                            {
                            case 0:
                                clientDataList[state.clientCounter].macAddress = receiveSplitData[0].ToString();
                                break;

                            case 1:
                                clientDataList[state.clientCounter].exitConnection = receiveSplitData[1].ToString();
                                break;

                            case 2:
                                clientDataList[state.clientCounter].nickName = receiveSplitData[2].ToString();
                                break;

                            case 3:
                                clientDataList[state.clientCounter].ufoPosition = receiveSplitData[3].ToString();
                                break;

                            case 4:
                                clientDataList[state.clientCounter].ufoVelocity = receiveSplitData[4].ToString();
                                break;

                            case 5:
                                clientDataList[state.clientCounter].ufoRotation = receiveSplitData[5].ToString();
                                break;

                            case 6:
                                // 다시 때린 UFO 맥 어드레스 데이터 분할하여 저장
                                string[] receiveSplitHittedUfoMac = receiveSplitData[6].Split('+');

                                // 해당 클라이언트가 때린 UFO 맥 어드레스 데이터를 배열로 전부 저장
                                for (int countHitUfo = 0; countHitUfo < receiveSplitHittedUfoMac.Length; countHitUfo++)
                                {
                                    clientDataList[state.clientCounter].hittedUfoMac[countHitUfo] = receiveSplitHittedUfoMac[countHitUfo].ToString();
                                }
                                break;

                            case 7:
                                // 다시 총알 데이터 분할하여 저장
                                string[] receiveSplitBullet = receiveSplitData[7].Split('+');

                                // 총알의 위치, 벡터, 생명시간 3가지의 요소를 각각의 총알 리스트로 저장
                                for (int countBul = 0; countBul <= (receiveSplitBullet.Length - 3); countBul += 3)
                                {
                                    clientDataList[state.clientCounter].bullet[countBul / 3].position = receiveSplitBullet[countBul].ToString();

                                    clientDataList[state.clientCounter].bullet[countBul / 3].velocity = receiveSplitBullet[countBul + 1].ToString();

                                    clientDataList[state.clientCounter].bullet[countBul / 3].remainingTime = receiveSplitBullet[countBul + 2].ToString();
                                }
                                break;
                            }
                        }

                        // 송신용 데이터 조합
                        CollectSendData(state.clientCounter);

                        // 수신이 끝났으니 이제 데이터 송신
                        workingSocket[state.clientCounter].BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None,
                                                                     new AsyncCallback(SendCall), state);
                    }
                }
                else
                {
                    // 수신받을 데이터가 없으면 수신 종료
                    Console.WriteLine(state.clientCounter + " 번 클라이언트로 부터 수신받을 데이터 없음...\n");
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("데이터 수신 실패...\n" + exc);
                return;
            }
        }