Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

윈폼개발

닷넷을 기반으로 한 윈도우 응용프로그램 개발 지식을 다룹니다. 비지니스 응용프로그램을 위한 닷넷 윈폼 응용프로그램은 아주 강력합니다

소켓 통신 시 데이타 송/수신

작성자 : 박종명
최초 작성일 : 2008-06-30 (월요일)
최종 수정일 : 2008-06-30 (월요일)
조회 수 : 3892

제가 운영하는 카페에 올라온 질문에 대한 답글 입니다.
질/답을 통해 소켓 통신 시 데이타를 송/수신 하는 방법에 대해 알아 봅니다.

질문>> ------------------------------------------------------------------------------------------------------------------------
제목도 뭐라고 써야할지 좀 난감 ㅋ

요즘 C#으로 네떡좀 만져볼라는데 상당히 거시기합니다. 

C/C++에서 다음과 같은 내용이 있습니다. 

typedef struct Data{
        int a;
        char b;
        char str[30];
};

Data data;
.......
char buffer[256];

memcpy(buffer, &data, sizeof(data));  

이렇게 마지막에 memcpy를 해주면 구조체가 갖고있는 메모리를 그대로 복사해올 수 있죠. 

혹은 

void OnReceivePacket(char* packet){
    Data* recvData = (Data*)packet;
} 

이 처럼 형 변환을 통해 간단히 Data 구조체를 얻어낼 수도 있구요. 

그런데 아직까지 제가 찾아본 결과로는... 

C#에서는 하나씩 변환해서 넣어주어야 하는 듯 합니다 

    public class Packet_CS_Hello {
        public Packet_CS_Hello(byte[] from)
        {
            size = BitConverter.ToUInt16(from, 0);
            id = BitConverter.ToUInt16(from, 2);

            data = BitConverter.ToUInt32(from, 4);
        }

        public UInt32 data;
        public ushort size;
        public ushort id;
    }

 이 방법 말고 좀 더 깔끔한 (unsafe 말구 ^^) 방법은 없을까요?

답변>> --------------------------------------------------------------------------------------------------------------------------------------------

소켓 통신 시 구조체를 많이 주고 받기는 합니다

그 방법에 대한 질문 같은데요.....

 

샘플을 가지고 이야기 해 보겠습니다

 

다음과 같은 구조체를 정의 합니다

 [Serializable]
 [StructLayout(LayoutKind.Sequential)]
 struct Data
 {
      [MarshalAs(UnmanagedType.U2, SizeConst = 2)]
      public ushort size;

 

      [MarshalAs(UnmanagedType.U2, SizeConst = 2)]
       public ushort id;

 

       [MarshalAs(UnmanagedType.U4, SizeConst = 4)]
       public UInt32 data;
  };

 

이 구조체를 바이트 배열로 변환 하여 네트워크 저 넘어로 전달하고 전달받은 곳에서는 다시 구조체로 변환하여

사용하고자 합니다

 

일단 동군님처럼 BitConvert 를 이용해서 하나하나 끊어서 값을 찾아 낼 수 도 있습니다

 ushort size = BitConverter.ToUInt16(bytesForWrite, 0);
 ushort id = BitConverter.ToUInt16(bytesForWrite, 2);
 UInt32 data = BitConverter.ToUInt32(bytesForWrite, 4);

 

 Data receiverData1;
 receiverData1.size = size;
 receiverData1.id = id;
 receiverData1.data = data;

 

 string result1 = String.Format("Size:{0},ID:{1},Data:{2}", receiverData1.size, receiverData1.id, receiverData1.data);
 Console.WriteLine(result1);

 

물론 이 방법은 구조체 멤버들의 정확한 크기에 맞는 적절한 Converting 을 해 주어야 하는 불편함이 있습니다

또한 구조체 멤버의 종류가 다양하면 캐안습(?) 일 수 도 있습니다 ㅋㅋ

 

 

그 다음으로는 BinaryFormatter 를 이용할 수 도 있습니다

NetworkStream 에 구조체를 Serialize 해서 수신측에서는 다시 Deserialize 하여 구조체를 얻는 방법입니다

, 마샬링을 이용하는 방법입니다

 BinaryFormatter formatter = new BinaryFormatter();

 Data receiverData = (Data) formatter.Deserialize(networkStream);

 

 

 

그 다음으로는 전달하는 데이터(위 구조체 Data) 구조체가 아니라 클래스로 정의된다면 다음 코드로도 가능합니다


 Data receiverData3;
 unsafe
 {
      fixed (byte* ptr = bytesForWrite)
      {
           Marshal.PtrToStructure((IntPtr)ptr, (Data)receiverData3);
       }
  }

 

 

 

여기서 제시된 샘플 프로젝트를 첨부 하였습니다. 다운로드 하여 실행 해 보신 후 참고하시길 바랍니다

 

그리고 마지막으로 덧붙이자면,

닷넷 환경에서 소켓을 굳이 고집할 필요는 없습니다

리모팅이나 닷넷 3.0 WCF 와 같은 닷넷 환경에 진보된 형태의 분산어플리케이션 구축도 고려해 볼 만 합니다

그러면 이와 같은 문제(?) 상황은 덜 하리라 보입니다

 

그럼.. ~ 프 하삼요~~

 

 


이름
비밀번호
홈페이지
GH <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요