public void receive() { if (stream_.DataAvailable) { Byte[] packetByte = new Byte[client_.ReceiveBufferSize]; Int32 offset = 0; Int32 readLen = stream_.Read(packetByte, offset, packetByte.Length); PacketObfuscation.decodingHeader(ref packetByte, sizeof(Int32)); Int32 packetLen = PacketUtil.decodePacketLen(packetByte, ref offset); while (readLen < packetLen) { Byte[] remainPacket = new Byte[client_.ReceiveBufferSize]; Int32 remainLen = 0; remainLen = stream_.Read(remainPacket, 0, remainPacket.Length); Buffer.BlockCopy(remainPacket, 0, packetByte, readLen, remainLen); readLen += remainLen; } Byte[] packetData = new Byte[client_.ReceiveBufferSize]; Buffer.BlockCopy(packetByte, offset, packetData, 0, readLen - offset); PacketObfuscation.decodingData(ref packetData, packetData.Length); Packetinterface rowPacket = PacketUtil.packetAnalyzer(packetData); if (rowPacket == null && this.isConnected()) { Debug.Log("잘못된 패킷이 수신되었습니다."); } ContentsProcee_.run(rowPacket); } }
public void receive() { try { while (this.isConnected()) { Byte[] packetByte = new Byte[client_.ReceiveBufferSize]; Int32 offset = 0; Int32 readLen = stream_.Read(packetByte, offset, packetByte.Length); // 패킷 난독화 PacketObfuscation.decodingHeader(ref packetByte, sizeof(Int32)); Int32 packetLen = PacketUtil.decodePacketLen(packetByte, ref offset); while (readLen < packetLen) { Byte[] remainPacket = new Byte[client_.ReceiveBufferSize]; Int32 remainLen = 0; remainLen = stream_.Read(remainPacket, 0, remainPacket.Length); Buffer.BlockCopy(remainPacket, 0, packetByte, readLen, remainLen); readLen += remainLen; } Byte[] packetData = new Byte[client_.ReceiveBufferSize]; Buffer.BlockCopy(packetByte, offset, packetData, 0, readLen - offset); PacketObfuscation.decodingData(ref packetData, packetData.Length); PacketInterface rowPacket = PacketUtil.packetAnalyzer(packetData); if (rowPacket == null && this.isConnected()) { //MessageBox.Show("잘못된 패킷이 수신되었습니다", "error", MessageBoxButtons.OK); //Application.Exit(); } packetProcee_.run(rowPacket); } this.close(); } catch (Exception e) { if (this.isConnected()) { //MessageBox.Show("잘못된 처리 : " + e.ToString(), "error", MessageBoxButtons.OK); //Application.Exit(); } } }
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); }