블로그 이미지
따시쿵

calendar

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

Notice

2015. 1. 17. 16:24 C# with TCP/IP

닷넷 환경에서 구조체를 이용한 소켓 통신을 지원하기 위한 방법은 크게 두 가지로 나뉩니다.


★ 마샬링(Marshaling)을 이용한 구조체 사용.

★ 바이너리 포매터(Binary Formatter)의 사용.


이번에는 마샬링 기법을 이용한 구조체를 통신하기 위한 방법을 소개합니다.


프로그램 설명


클라이언트가 학생의 4가지 데이타(이름, 과목, 점수, 메모)를 서버로 전송한다고 가정하고 필요한 클래스는 아래와 같습니다.

    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. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.

using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;


2. 서버 프로그램


    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. 클라이언트 프로그램


    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;
    }


posted by 따시쿵