닷넷 환경에서 구조체를 이용한 소켓 통신을 지원하기 위한 방법은 크게 두 가지로 나뉩니다.
★ 마샬링(Marshaling)을 이용한 구조체 사용.
★ 바이너리 포매터(Binary Formatter)의 사용.
이번에는 마샬링 기법을 이용한 구조체를 통신하기 위한 방법을 소개합니다.
프로그램 설명
클라이언트가 학생의 4가지 데이타(이름, 과목, 점수, 메모)를 서버로 전송한다고 가정하고 필요한 클래스는 아래와 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class DataPacket { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Name; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Subject; [MarshalAs(UnmanagedType.I4)] public int Grade; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] public string Memo; } |
실행 후
메시지 전송 후
프로그램 작성 순서
1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.
1 2 3 4 | using System.Net; using System.Net.Sockets; using System.Threading; using System.Diagnostics; |
2. 서버 프로그램
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | class Program { static void Main( string [] args) { TcpListener server = null ; try { server = new TcpListener(IPAddress.Parse( "192.168.0.12" ), 13000); server.Start(); byte [] buffer = new byte [8092]; while ( true ) { Console.WriteLine( "Waiting for a connection....." ); TcpClient client = server.AcceptTcpClient(); Console.WriteLine( "\nConnected!!" ); NetworkStream stream = client.GetStream(); DataPacket packet = new DataPacket(); //buffer = null; while (stream.Read(buffer, 0, Marshal.SizeOf(packet)) != 0) { unsafe { fixed ( byte * fixed_buffer = buffer) { Marshal.PtrToStructure((IntPtr)fixed_buffer, packet); } } string Name = packet.Name; string Subject = packet.Subject; Int32 Grade = packet.Grade; string Memo = packet.Memo; Console.WriteLine( "이 름 : {0}" , Name); Console.WriteLine( "과 목 : {0}" , Subject); Console.WriteLine( "점 수 : {0}" , Grade); Console.WriteLine( "메 모 : {0}" , Memo); Console.WriteLine( "" ); Console.WriteLine( "===========================================" ); Console.WriteLine( "" ); } stream.Close(); client.Close(); } } catch (SocketException se) { Console.WriteLine(se.Message.ToString()); } catch (Exception ex) { Console.WriteLine(ex.Message.ToString()); } Console.ReadLine(); } } [StructLayout(LayoutKind.Sequential)] class DataPacket { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Name; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Subject; [MarshalAs(UnmanagedType.I4)] public int Grade; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] public string Memo; } |
3. 클라이언트 프로그램
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | class Program { static void Main( string [] args) { try { string Name = string .Empty; string Subject = string .Empty; Int32 Grade = 0; string Memo = string .Empty; do { Console.Write( "이름 : " ); Name = Console.ReadLine(); Console.Write( "과목 : " ); Subject = Console.ReadLine(); Console.Write( "점수 : " ); string tmpGrage = Console.ReadLine(); if (tmpGrage != "" ) Grade = Convert.ToInt32(tmpGrage); else Grade = 0; Console.Write( "메모 : " ); Memo = Console.ReadLine(); if ( string .IsNullOrEmpty(Name) || string .IsNullOrEmpty(Subject)) break ; // 전송할 데이타 가공하기 DataPacket packet = new DataPacket(); packet.Name = Name; packet.Subject = Subject; packet.Grade = Grade; packet.Memo = Memo; byte [] buffer = new byte [Marshal.SizeOf(packet)]; unsafe { fixed ( byte * fixed_buffer = buffer) { Marshal.StructureToPtr(packet, (IntPtr)fixed_buffer, false ); } } // 데이타 전송하기 TcpClient client = new TcpClient(); client.Connect( "192.168.0.12" , 13000); Console.WriteLine( "Connected..." ); NetworkStream stream = client.GetStream(); stream.Write(buffer, 0, Marshal.SizeOf(packet)); Console.WriteLine( "{0} data sent\n" , Marshal.SizeOf(packet)); stream.Close(); client.Close(); } while (Name != "" && Subject != "" ); } catch (SocketException se) { Console.WriteLine(se.Message.ToString()); } catch (Exception ex) { Console.WriteLine(ex.Message.ToString()); } Console.WriteLine( "\nPress enter key to continue...." ); Console.ReadLine(); } } [StructLayout(LayoutKind.Sequential)] class DataPacket { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Name; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Subject; [MarshalAs(UnmanagedType.I4)] public int Grade; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] public string Memo; } |
'C# with TCP/IP' 카테고리의 다른 글
[Program C#]구조체를 이용한 소켓통신2 - 마샬링 방법 - 콘솔 버전 (0) | 2015.01.21 |
---|---|
[Program C#]구조체를 이용한 소켓통신1 - 마샬링 방법 - 윈도우 버전 (0) | 2015.01.20 |
[Program C#]TcpListener - TcpClient 응용1 - 윈도우 버전 (1) | 2015.01.15 |
[Program C#]TcpListener - TcpClient msdn 예제 - 윈도우 버전 (1) | 2015.01.13 |
[Program C#]TcpListener - TcpClient msdn 예제 - 콘솔 버전 (0) | 2015.01.09 |