소켓통신으로 객체를 마샬링하여 통째로 전달하여 보자.

우리가 소켓통신을 사용하다 보면 배열이나 구조체를 통째로

날리면 편하겠다 라는 생각을 많이 하게 된다.

먼저 우리가 알아두어야 할 개념이 있다.

MarshalAsAttribute의 설명

이 특성은 매개 변수, 필드 또는 반환 값에 적용될 수 있습니다.

각 데이터 형식에 기본 마샬링 동작이 있으므로 이 특성은 선택적입니다. 이 특성은 주어진 형식을 여러 형식으로 마샬링할 수 있는 경우에만 필요합니다. 예를 들어, 문자열은 LPStr, LPWStr, LPTStr 또는 BStr로 관리되지 않는 코드로 마샬링할 수 있습니다. 기본적으로 공용 언어 런타임에서는 문자열 매개 변수를 BStr로 COM 메서드로 마샬링합니다. MarshalAsAttribute 속성을 개별 필드나 매개 변수에 적용하여 특정 문자열이 BStr 대신 LPStr로 마샬링되도록 할 수 있습니다. 형식 라이브러리 내보내기(Tlbexp.exe)는 사용자의 마샬링 기본 설정을 공용 언어 런타임에 전달합니다.

일부 매개 변수 및 반환 값은 COM interop 또는 플랫폼 호출과 함께 사용할 경우 기본 마샬링 동작이 다릅니다. 기본적으로 런타임에서는 문자열 매개 변수 및 값 형식의 필드를 LPStr로 플랫폼 호출 메서드 또는 함수로 마샬링합니다. 자세한 내용은 기본 마샬링 동작을 참조하십시오.

대부분의 경우 이 특성은 다음 C# 시그니처와 같이 UnmanagedType 열거형을 사용하는 관리되지 않는 데이터의 형식을 쉽게 식별합니다.

void MyMethod([MarshalAs(LPStr)] String s);

일부 UnmanagedType 열거형 멤버에는 추가 정보가 필요합니다. 예를 들어, UnmanagedTypeLPArray 일 때에는 추가 정보가 필요합니다. 이 특성을 배열에 사용하는 방법에 대한 자세한 내용은배열에 대한 기본 마샬링을 참조하십시오.

형식 라이브러리 가져오기(Tlbimp.exe)는 이 특성을 매개 변수, 필드 및 반환 값에도 적용하여 입력 형식 라이브러리의 데이터 형식이 해당 관리되는 데이터 형식의 기본 형식이 아님을 나타냅니다. Tlbimp.exe는 입력 형식 라이브러리에 지정된 형식에 상관없이 명확함을 기하기 위해 StringObject 형식에 항상 MarshalAsAttribute를 적용합니다.


예제를 보자.


[C#]

//Applied to a parameter.

  public void M1 ([MarshalAs(UnmanagedType.LPWStr)]String msg);

//Applied to a field within a class.

  class MsgText {

    [MarshalAs(UnmanagedType.LPWStr)] Public String msg;

  }

//Applied to a return value.

[return: MarshalAs(UnmanagedType.LPWStr)]

public String GetMessage();

 

이 마샬링의 개념이 정리가 되었으면 이제  관리되지 않는 메모리 블록의 데이터를

관리되는 개체로 마샬링하는 메서드를 정리 해보도록 하자.


Marshal.PtrToStructure 메서드사용 예제

UCOMITypeInfo typeInfo = ...;

IntPtr ptr = IntPtr.Zero;

typeInfo.GetTypeAttr(ref ptr);

TYPEATTR attr = (TYPEATTR)Marshal.PtrToStructure(ptr,

    typeof(TYPEATTR));





실전 객체 전달 프로그래밍


using System.Runtime.InteropServices; //관리되지않는 코드 (포인터 사용및 구조체를 시퀜셜하게 만들기위해)

using System.Text;

using System.Net.Sockets;

using System.Diagnostics;  


// 클래스(구조체) 샘플.

[StructLayout(LayoutKind.Sequential)]

public class TempPacket

{

    public byte Command;

    public byte Version;

    public ushort Length;        

    [MarshalAs(UnmanagedType.ByValArray, SizeConst=10)] public byte[] Data;  //바이트 배열....

}


public class Sample

{

    public void Text()

    {

        TempPacket tmpPacket = new TempPacket();


        tmpPacket.Command = 0x10;

        tmpPacket.Version = 0x01;

        tmpPacket.Length = 10;

        tmpPacket.Data = Encoding.ASCII.GetBytes("0123456789");


        //객체를 보내보자.                    

        byte[] buffer = new byte[Marshal.SizeOf(tmpPacket)];

        unsafe

        {

            fixed(byte* fixed_buffer = buffer)

            {

                Marshal.StructureToPtr(tmpPacket, (IntPtr)fixed_buffer, false);

            }

        }

   

        //소켓열고        

        TcpClient tcpClient = new TcpClient();

        tcpClient.Connect("localhost", 8296);

   

        NetworkStream networkStream = tcpClient.GetStream();

   

        networkStream.Write(buffer, 0, Marshal.SizeOf(tmpPacket));

               

        //객체받고

        TempPacket tmpPacket2 = new TempPacket();

        networkStream.Read(buffer, 0, Marshal.SizeOf(tmpPacket));

        unsafe

        {

            fixed(byte* fixed_buffer = buffer)

            {

                Marshal.PtrToStructure((IntPtr)fixed_buffer, tmpPacket2);

            }

        }    

        string data;

   

        data = Encoding.ASCII.GetString(tmpPacket2.Data, 0, 10);

        Debug.WriteLine(data);

        networkStream.Close();

        tcpClient.Close();

    }

}


 


  작성자 : HOONS(박경훈)
  이메일 : tajopkh@hanmail.net
  홈페이지 : http://www.hoonsbara.com 

신고
Posted by 나비 나비:D
태그

BLOG main image
by 나비:D

공지사항

카테고리

분류 전체보기 (278)
Programming? (0)
----------------------------- (0)
나비의삽질 (5)
Application (177)
SQL (51)
Web (27)
etc. (14)
Omnia (0)
---------------------------.. (0)

글 보관함

달력

«   2017/08   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
Total : 870,708
Today : 10 Yesterday : 157