public override void parse(Packetinterface packet) { PacketType type = (PacketType)packet.getType(); Debug.Log("받은 게임 패킷 : " + type); switch (type) { case PacketType.E_S_ANS_EXIT: gamePacketProcess.S_ANS_EXIT(packet); return; case PacketType.E_S_ANS_CONNECT: gamePacketProcess.S_ANS_CONNECT(packet); return; case PacketType.E_S_NOTIFY_OTHER_CLIENT: gamePacketProcess.S_NOTIFY_CLIENT_DATA(packet); return; case PacketType.E_S_ANS_MOVE: gamePacketProcess.S_ANS_MOVE(packet); return; case PacketType.E_S_NOTIFY_USER_DATA: gamePacketProcess.S_NOTIFY_USER_DATA(packet); return; default: Debug.Log("잘못된 패킷이 수신되었습니다. : "); Debug.Log(type); break; } /* * if (base.defaultRun(packet) == false) * { #if DEBUG * Debug.Log("잘못된 패킷이 수신되었습니다. : "); * Debug.Log(type); #endif * } */ }
private void receive_CallBack(IAsyncResult ar) { Data data = (Data)ar.AsyncState; Socket localSocket = data.socket; Byte[] packetHeader = new Byte[sizeof(Int32)]; Byte[] packetBody = new Byte[1024]; // 임의 크기로 해놈 Int32 readLen = localSocket.EndReceive(ar); if (readLen == 0) { Debug.Log("Zero Receive Error"); return; } //들어온 크기만 큼 packetByte에 복사한다. Buffer.BlockCopy(data.buff, 0, packetBytes, totalBytes, readLen); totalBytes += readLen; Debug.Log("Receive Size : " + readLen.ToString() + "TotalBytes Size : " + totalBytes.ToString()); while (totalBytes > 0) { // Array.Clear(packetHeader, 0, sizeof(Int32)); // Array.Clear(packetBody, 0, sizeof(Byte) * 1024); Int32 currentOffset = 0; Int32 offset = 0; Buffer.BlockCopy(packetBytes, currentOffset, packetHeader, 0, sizeof(Int32)); // //packet 버퍼에 있는 크기가 헤더 이하이면 if (totalBytes < BitConverter.ToInt32(packetHeader, 0)) { Debug.Log("totalBytes is not enough "); break; //localSocket.BeginReceive(data.buff, 0, Data.BuffSize, 0, new AsyncCallback(receive_CallBack), data); //return; } //packet 버퍼에 있는 크기가 헤더 이상이라면 //packetHeader 에 packetheader 만큼 복사. // Buffer.BlockCopy(packetBytes, currentOffset, packetHeader, 0, sizeof(Int32)); // currentOffset += sizeof(Int32); // packetByte의 offset 변경 // 패킷 총 길이를 가져옴. + offset 증가 Int32 packetLen = PacketUtil.decodePacketLen(packetHeader, ref offset); packetLen -= offset; int remainBytes = totalBytes - currentOffset; // packetData에서 헤더를 제외한 남은 바이트 if (remainBytes < packetLen) { Debug.Log("remainBytes is Not enough"); break; //localSocket.BeginReceive(data.buff, 0, Data.BuffSize, 0, new AsyncCallback(receive_CallBack), data); /* * * */ //return; } // currentOffset 은 패킷 헤더 이후의 offset Buffer.BlockCopy(packetBytes, currentOffset, packetBody, 0, packetLen); currentOffset += packetLen; Packetinterface rowPacket = PacketUtil.packetAnalyzer(packetBody, packetLen); Debug.Log("Receive Packet : " + rowPacket.getType().ToString()); if (rowPacket == null && localSocket.Connected) { Debug.Log("잘못된 패킷이 수신되었습니다."); } // 큐 구분 해야됨. if (PacketQueue == readPacketQueue) { lock (writePacketQueue) { writePacketQueue.Enqueue(rowPacket); } } else { lock (readPacketQueue) { readPacketQueue.Enqueue(rowPacket); } } //writePacketQueue //Enqueue(rowPacket); //packetBytes 를 사용 했으므로 data 및 offset 수정 // Buffer.BlockCopy(packetBytes, 0, packetBytes, currentOffset, totalBytes - currentOffset); Buffer.BlockCopy(packetBytes, currentOffset, packetBytes, 0, totalBytes - currentOffset); totalBytes -= currentOffset; /* * 생각할 수 있는 것은 Client에서의 Enqueue 와 Dequeue 사이에서 Lock으로 인한 병목현상이다. * 클라이언트의 Network 는 하나의 스레드가 온전히 recv 하고 enqueue 를 실행하지만 * 클라이언트의 Unity Script 에서는 하나의 스레드가 실행 시간을 나누어 dequeue를 실행한다 * * * 11/20 * * PacketQueue 에서 Dequeue 하는 부분의 Corutine의 갯수를 증가시켰을때 * 전 보다 싱크 의 차이가 줄어드는 것을 확인할 수 있었음. * 즉 병목현상이 맞다고 판단 -> Server와 동일하게 두 개의 버퍼를 만들어 스왚하는 로직을 통해 해소해보자. */ } Array.Clear(data.buff, 0, readLen); localSocket.BeginReceive(data.buff, 0, Data.BuffSize, 0, new AsyncCallback(receive_CallBack), data); }