블로그 이미지
따시쿵

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

Notice

2015. 1. 27. 07:39 C# with TCP/IP

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


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

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


이번에는 바이너리 포매터 기법을 이용한 구조체를 통신하기 위한 방법을 소개합니다.


프로그램 설명


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

DataPacket.cs

 

    [Serializable]
    struct DataPacket
    {
        public string Name;
        public string Subject;
        public int Grade;
        public string Memo;
    }


실행 후


메시지 전송 후



프로그램 작성 순서


1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.

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


2. 서버 프로그램

        TcpListener server = null;
        public MainForm()
        {
            InitializeComponent();
            FormClosing += new FormClosingEventHandler(WindowsFormClosing);
            InitStart();
        }

        private void WindowsFormClosing(object sender, FormClosingEventArgs s)
        {
            if (server != null)
                server = null;

            Application.Exit();
        }
        private void InitStart()
        {
            Thread socketworker = new Thread(new ThreadStart(socketThread));
            socketworker.IsBackground = true;
            socketworker.Start();
        }

        private void socketThread()
        {
            try
            {
                server = new TcpListener(IPAddress.Parse("192.168.0.12"), 13000);
                server.Start();

                while (true)
                {
                    TcpClient client = server.AcceptTcpClient();
                    updateStatusInfo("Connected");
                    Thread clientworker = new Thread(new ParameterizedThreadStart(clientThread));
                    clientworker.IsBackground = true;
                    clientworker.Start(client);
                }
            }
            catch (SocketException se)
            {
                Debug.WriteLine("SocketException : {0}", se.Message);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception : {0}", ex.Message);
            }
        }

        private void clientThread(object sender)
        {
            // 1. 데이타 받기
            TcpClient client = sender as TcpClient;
            NetworkStream stream = client.GetStream();

            byte[] buffer = new byte[8092];
            DataPacket packet = new DataPacket();

            while (stream.Read(buffer, 0, buffer.Length) != 0)
            {
                // deserializing; 
                packet = GetBindAck(buffer);
            }

            stream.Close();
            client.Close();

            // 2. 데이타 표시하기
            string Name = packet.Name;
            string Subject = packet.Subject;
            Int32 Grade = packet.Grade;
            string Memo = packet.Memo;

            Debug.WriteLine("{0} : {1} : {2} : {3}", Name, Subject, Grade, Memo);

            Invoke((MethodInvoker)delegate
            {
                int count = listView1.Items.Count;
                count++;

                ListViewItem i = new ListViewItem();
                i.Text = count.ToString();
                i.SubItems.Add(Name);
                i.SubItems.Add(Subject);
                i.SubItems.Add(Grade.ToString());
                i.SubItems.Add(Memo);
                i.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                listView1.Items.Add(i);

                listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            });


            // 3. 상태값 표시하기
            updateStatusInfo("Data Accepted");
        }

        private void updateStatusInfo(string content)
        {
            Action del = delegate()
            {
                lblStatus.Text = content;
            };
            Invoke(del);
        }

        private void btnDataClear_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("데이타를 모두 삭제 하시겠습니까?", "질문", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK)
            {
                listView1.Items.Clear();
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private DataPacket GetBindAck(byte[] btfuffer)
        {
            DataPacket packet = new DataPacket();

            MemoryStream ms = new MemoryStream(btfuffer, false);
            BinaryReader br = new BinaryReader(ms);

            packet.Name = ExtendedTrim(Encoding.UTF8.GetString(br.ReadBytes(20)));
            packet.Subject = ExtendedTrim(Encoding.UTF8.GetString(br.ReadBytes(20)));
            packet.Grade = IPAddress.NetworkToHostOrder(br.ReadInt32());
            packet.Memo = ExtendedTrim(Encoding.UTF8.GetString(br.ReadBytes(100)));

            br.Close();
            ms.Close();

            return packet;
        }

        // 문자열 뒤쪽에 위치한 null 을 제거한 후에 공백문자를 제거한다.
        private string ExtendedTrim(string source)
        {
            string dest = source;
            int index = dest.IndexOf('\0');
            if (index > -1)
            {
                dest = source.Substring(0, index + 1);
            }

            return dest.TrimEnd('\0').Trim();
        }


3. 클라이언트 프로그램


        public MainForm()
        {
            InitializeComponent();

            btnSend.MouseEnter += new EventHandler(btnSend_MouseEnter);
            btnSend.MouseLeave += new EventHandler(btnSend_MouseLeave);
        }

        void btnSend_MouseEnter(object sender, EventArgs e)
        {
            btnSend.UseVisualStyleBackColor = false;
            btnSend.BackColor = Color.FromArgb(255, 255, 165, 00);  // 배경색을 오렌지 색으로 변경함...
            btnSend.ForeColor = Color.White;                        // 글자색을 흰색으로 변경함
        }

        void btnSend_MouseLeave(object sender, EventArgs e)
        {
            btnSend.UseVisualStyleBackColor = true;
            btnSend.BackColor = SystemColors.Control;               // 배경색을 시스템 기본색으로 변경함...
            btnSend.ForeColor = SystemColors.ControlText;           // 글자색을 시스템 기본색으로 변경함...
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            Thread socketworker = new Thread(new ThreadStart(socketThread));
            socketworker.IsBackground = true;
            socketworker.Start();
        }

        private void socketThread()
        {
            // 1. 데이타패킷 조합
            Debug.WriteLine("{0} : {1} : {2} : {3}", txtName.Text, txtSubject.Text, txtGrade.Text, txtMemo.Text);

            DataPacket packet = new DataPacket();

            packet.Name = txtName.Text;
            packet.Subject = txtSubject.Text;

            Int32 outNum;
            if (Int32.TryParse(txtGrade.Text, out outNum))
            {
                packet.Grade = Convert.ToInt32(txtGrade.Text);
            }
            else
            {
                packet.Grade = 0;
            }

            packet.Memo = txtMemo.Text;

            if (string.IsNullOrEmpty(packet.Name))
            {
                MessageBox.Show("[이 름]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtName.Focus();

                });
                return;
            }

            if (string.IsNullOrEmpty(packet.Subject))
            {
                MessageBox.Show("[과 목]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtSubject.Focus();

                });
                return;
            }

            if (packet.Grade == 0)
            {
                MessageBox.Show("[점 수]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtGrade.Focus();

                });
                return;
            }

            if (string.IsNullOrEmpty(packet.Memo))
            {
                packet.Memo = " ";
            }

            // 2. TcpClient 생성 및 설정
            TcpClient client = new TcpClient(txtServerIP.Text, Convert.ToInt32(txtServerPort.Text));
            NetworkStream stream = client.GetStream();
            updateStatusInfo("Connected");

            // 3. 전송하기
            byte[] buffer = GetBytes_Bind(packet);

            stream.Write(buffer, 0, buffer.Length);
            updateStatusInfo(string.Format("{0} data sent", buffer.Length));

            // 4. 스트림과 소켓 닫기
            stream.Close();
            client.Close();

            // 5. listview 에 추가하기
            Invoke((MethodInvoker)delegate
            {
                int count = listView1.Items.Count;
                count++;

                ListViewItem i = new ListViewItem();
                i.Text = count.ToString();
                i.SubItems.Add(txtName.Text);
                i.SubItems.Add(txtSubject.Text);
                i.SubItems.Add(txtGrade.Text);
                i.SubItems.Add(txtMemo.Text);
                i.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                listView1.Items.Add(i);

                listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            });
        }

        private void updateStatusInfo(string content)
        {
            Action del = delegate()
            {
                lblStatus.Text = content;
            };
            Invoke(del);
        }

        // 패킷 사이즈 
        private const int BODY_BIND_SIZE = 20 + 20 + 4 + 100;

        // 인증 패킷 구조체를 바이트 배열로 변환하는 함수
        private byte[] GetBytes_Bind(DataPacket packet)
        {
            byte[] btBuffer = new byte[BODY_BIND_SIZE];

            MemoryStream ms = new MemoryStream(btBuffer, true);
            BinaryWriter bw = new BinaryWriter(ms);

            // Name - string
            try
            {
                byte[] btName = new byte[20];
                Encoding.UTF8.GetBytes(packet.Name, 0, packet.Name.Length, btName, 0);
                bw.Write(btName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : {0}", ex.Message.ToString());
            }

            // Subject - string
            try
            {
                byte[] btName = new byte[20];
                Encoding.UTF8.GetBytes(packet.Subject, 0, packet.Subject.Length, btName, 0);
                bw.Write(btName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : {0}", ex.Message.ToString());
            }

            // Grade - long
            bw.Write(IPAddress.HostToNetworkOrder(packet.Grade));

            // Memo - string
            try
            {
                byte[] btName = new byte[100];
                Encoding.UTF8.GetBytes(packet.Memo, 0, packet.Memo.Length, btName, 0);
                bw.Write(btName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : {0}", ex.Message.ToString());
            }

            bw.Close();
            ms.Close();

            return btBuffer;
        }


posted by 따시쿵
2015. 1. 26. 17:50 C# with TCP/IP

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


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

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


이번에는 바이너리 포매터 기법을 이용한 구조체를 통신하기 위한 방법을 소개합니다.


프로그램 설명


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

DataPacket.cs

    [Serializable]
    struct DataPacket
    {
        public string Name;
        public string Subject;
        public int Grade;
        public string Memo;
    }


실행 후


메시지 전송 후


프로그램 작성 순서


1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.

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


2. 서버 프로그램

        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[256];

                while(true)
                {
                    Console.WriteLine("Waiting for a connection.....");

                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("\nConnected!!");

                    NetworkStream stream = client.GetStream();                    

                    while(stream.Read(buffer, 0, buffer.Length) != 0)
                    {
                        DataPacket packet = GetBindAck(buffer);

                        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("SocketException : {0}", se.Message);
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception : {0}", ex.Message);
            }
        }

        private static DataPacket GetBindAck(byte[] btfuffer)
        {
            DataPacket packet = new DataPacket();

            MemoryStream ms = new MemoryStream(btfuffer, false);
            BinaryReader br = new BinaryReader(ms);
                        
            packet.Name = ExtendedTrim(Encoding.UTF8.GetString(br.ReadBytes(20)));
            packet.Subject = ExtendedTrim(Encoding.UTF8.GetString(br.ReadBytes(20)));
            packet.Grade = IPAddress.NetworkToHostOrder(br.ReadInt32());
            packet.Memo = ExtendedTrim(Encoding.UTF8.GetString(br.ReadBytes(100)));

            br.Close();
            ms.Close();

            return packet;
        }

        // 문자열 뒤쪽에 위치한 null 을 제거한 후에 공백문자를 제거한다.
        private static string ExtendedTrim(string source)
        {
            string dest = source;
            int index = dest.IndexOf('\0');
            if (index > -1)
            {
                dest = source.Substring(0, index + 1);
            }

            return dest.TrimEnd('\0').Trim();
        }


3. 클라이언트 프로그램


        static void Main(string[] args)
        {
            try
            {
                string Name = string.Empty;
                string Subject = string.Empty;
                Int32 Grade = 0;
                string Memo = string.Empty;

                do
                {
                    // 1. 데이타 입력
                    Console.Write("이름 : ");
                    Name = Console.ReadLine();

                    Console.Write("과목 : ");
                    Subject = Console.ReadLine();

                    Console.Write("점수 : ");
                    string tmpGrage = Console.ReadLine();
                    if (tmpGrage != "")
                    {
                        int outGrade = 0;
                        if (Int32.TryParse(tmpGrage, out outGrade))
                            Grade = Convert.ToInt32(tmpGrage);
                        else
                            Grade = 0;
                    }
                    else
                        Grade = 0;

                    Console.Write("메모 : ");
                    Memo = Console.ReadLine();

                    if (string.IsNullOrEmpty(Name) || string.IsNullOrEmpty(Subject))
                        break;

                    // 2. 구조체 데이타를 바이트 배열로 변환
                    DataPacket packet = new DataPacket();
                    packet.Name = Name;
                    packet.Subject = Subject;
                    packet.Grade = Grade;
                    packet.Memo = Memo;

                    byte[] buffer = GetBytes_Bind(packet);

                    // 3. 데이타 전송
                    TcpClient client = new TcpClient();
                    client.Connect("192.168.0.12", 13000);
                    Console.WriteLine("Connected...");

                    NetworkStream stream = client.GetStream();

                    stream.Write(buffer, 0, buffer.Length);
                    Console.WriteLine("{0} data sent\n", buffer.Length);

                    stream.Close();
                    client.Close();
                } while (Name != "" && Subject != "");
            }
            catch (SocketException se)
            {
                Console.WriteLine("SocketException : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception : {0} ", ex.Message.ToString());
            }

            Console.WriteLine("press the ENTER to continue...");
            Console.ReadLine();
        }


        // 패킷 사이즈 
        public const int BODY_BIND_SIZE = 20 + 20 + 4 + 100;

        // 인증 패킷 구조체를 바이트 배열로 변환하는 함수
        public static byte[] GetBytes_Bind(DataPacket packet)
        {
            byte[] btBuffer = new byte[BODY_BIND_SIZE];

            MemoryStream ms = new MemoryStream(btBuffer, true);
            BinaryWriter bw = new BinaryWriter(ms);

            // Name - string
            try
            {
                byte[] btName = new byte[20];
                Encoding.UTF8.GetBytes(packet.Name, 0, packet.Name.Length, btName, 0);
                bw.Write(btName);
            }
            catch(Exception ex)
            {
                Console.WriteLine("Error : {0}", ex.Message.ToString());
            }

            // Subject - string
            try
            {
                byte[] btName = new byte[20];
                Encoding.UTF8.GetBytes(packet.Subject, 0, packet.Subject.Length, btName, 0);
                bw.Write(btName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : {0}", ex.Message.ToString());
            }

            // Grade - long
            bw.Write(IPAddress.HostToNetworkOrder(packet.Grade));

            // Memo - string
            try
            {
                byte[] btName = new byte[100];
                Encoding.UTF8.GetBytes(packet.Memo, 0, packet.Memo.Length, btName, 0);
                bw.Write(btName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error : {0}", ex.Message.ToString());
            }

            bw.Close();
            ms.Close();

            return btBuffer;
        }


posted by 따시쿵
2015. 1. 24. 10:07 C#

1. 

메인 폼에서 showDialog 를 이용해서 폼 Form2 를 새로 만듭니다.

Form2 창에서 OK, Cancel 버튼을 선택하는 것을 보여 주는 예제입니다.


실행화면




프로그램


1. 메인 창

        private void btnFormTwo_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            if (f2.ShowDialog() == DialogResult.OK)
                MessageBox.Show("OK button clicked");
            else if (f2.ShowDialog() == DialogResult.Cancel)
                MessageBox.Show("Cancel button clicked");
        }


2. Form2

        private void btnOK_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
        }


2.

메인 창에서 Form2를 띄웁니다. 메인창에 있는 textbox 를 Form2 에 전달하고, Form2 에서 대문자, 소문자로 변경한 내용을 다시 메인창의 텍스트박스에서 보여지게 합니다.


실행화면






프로그램


1. 메인 창

        public static TextBox tb = new TextBox();
        private void btnChangeCase_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            if (f2.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                MessageBox.Show("OK");
            else
                MessageBox.Show("Cancel");
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            tb = txtChangeCase;
        }


2. Form2

using System.Globalization;
using System.Threading;

        private void btnOK_Click(object sender, EventArgs e)
        {
            string changeCase = MainForm.tb.Text;

            if (radioButton1.Checked)
                changeCase = changeCase.ToUpper();
            else if (radioButton2.Checked)
                changeCase = changeCase.ToLower();
            else if (radioButton3.Checked)
            {
                CultureInfo properCase = Thread.CurrentThread.CurrentCulture;
                TextInfo textInfoObject = properCase.TextInfo;

                changeCase = textInfoObject.ToTitleCase(changeCase);
            }

            MainForm.tb.Text = changeCase;

            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
        }

posted by 따시쿵
2015. 1. 22. 11:23 C# with TCP/IP

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


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

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


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


프로그램 설명


클라이언트가 학생의 4가지 데이타(이름, 과목, 점수, 메모)를 서버로 전송한다고 가정하고 필요한 클래스는 아래와 같습니다. 메소드 Serialize(), Deserialize(ref byte[] data) 가 구조체에서 배열로, 배열에서 구조체로 변경해 주는 기능을 담당하고 있습니다.

DataPacket.cs

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    struct 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;

        // Calling this method will return a byte array with the contents
        // of the struct ready to be sent via the tcp socket.
        public byte[] Serialize()
        {
            // allocate a byte array for the struct data
            var buffer = new byte[Marshal.SizeOf(typeof(DataPacket))];

            // Allocate a GCHandle and get the array pointer
            var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            var pBuffer = gch.AddrOfPinnedObject();

            // copy data from struct to array and unpin the gc pointer
            Marshal.StructureToPtr(this, pBuffer, false);
            gch.Free();

            return buffer;
        }

        // this method will deserialize a byte array into the struct.
        public void Deserialize(ref byte[] data)
        {
            var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
            this = (DataPacket)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(DataPacket));
            gch.Free();
        }
    }


실행 후



메시지 전송 후



프로그램 작성 순서


1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.

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


2. 서버 프로그램


    public partial class MainForm : Form
    {
        TcpListener server = null;
        public MainForm()
        {
            InitializeComponent();
            FormClosing += new FormClosingEventHandler(WindowsFormClosing);
            InitStart();
        }

        private void WindowsFormClosing(object sender, FormClosingEventArgs s)
        {
            if (server != null)
                server = null;

            Application.Exit();
        }
        private void InitStart()
        {
            Thread socketworker = new Thread(new ThreadStart(socketThread));
            socketworker.IsBackground = true;
            socketworker.Start();
        }

        private void socketThread()
        {
            try
            {
                server = new TcpListener(IPAddress.Parse("192.168.0.12"), 13000);
                server.Start();

                while (true)
                {
                    TcpClient client = server.AcceptTcpClient();
                    updateStatusInfo("Connected");
                    Thread clientworker = new Thread(new ParameterizedThreadStart(clientThread));
                    clientworker.IsBackground = true;
                    clientworker.Start(client);
                }
            }
            catch (SocketException se)
            {
                Debug.WriteLine("SocketException : {0}", se.Message);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception : {0}", ex.Message);
            }
        }

        private void clientThread(object sender)
        {
            // 1. 데이타 받기
            TcpClient client = sender as TcpClient;
            NetworkStream stream = client.GetStream();
            
            byte[] buffer = new byte[8092];
            DataPacket packet = new DataPacket();

            while (stream.Read(buffer, 0, buffer.Length) != 0)
            {
                // deserializing;                
                packet.Deserialize(ref buffer);
            }

            stream.Close();
            client.Close();

            // 2. 데이타 표시하기
            string Name = packet.Name;
            string Subject = packet.Subject;
            Int32 Grade = packet.Grade;
            string Memo = packet.Memo;

            Debug.WriteLine("{0} : {1} : {2} : {3}", Name, Subject, Grade, Memo);

            Invoke((MethodInvoker)delegate
            {
                int count = listView1.Items.Count;
                count++;

                ListViewItem i = new ListViewItem();
                i.Text = count.ToString();
                i.SubItems.Add(Name);
                i.SubItems.Add(Subject);
                i.SubItems.Add(Grade.ToString());
                i.SubItems.Add(Memo);
                i.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                listView1.Items.Add(i);

                listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            });

            
            // 3. 상태값 표시하기
            updateStatusInfo("Data Accepted");
        }

        private void updateStatusInfo(string content)
        {
            Action del = delegate()
            {
                lblStatus.Text = content;
            };
            Invoke(del);
        }

        private void btnDataClear_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("데이타를 모두 삭제 하시겠습니까?", "질문", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK)
            {
                listView1.Items.Clear();
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }


3. 클라이언트 프로그램


        public MainForm()
        {
            InitializeComponent();

            btnSend.MouseEnter += new EventHandler(btnSend_MouseEnter);
            btnSend.MouseLeave += new EventHandler(btnSend_MouseLeave);
        }

        void btnSend_MouseEnter(object sender, EventArgs e)
        {
            btnSend.UseVisualStyleBackColor = false;
            btnSend.BackColor = Color.FromArgb(255, 255, 165, 00);  // 배경색을 오렌지 색으로 변경함...
            btnSend.ForeColor = Color.White;                        // 글자색을 흰색으로 변경함
        }

        void btnSend_MouseLeave(object sender, EventArgs e)
        {
            btnSend.UseVisualStyleBackColor = true;
            btnSend.BackColor = SystemColors.Control;               // 배경색을 시스템 기본색으로 변경함...
            btnSend.ForeColor = SystemColors.ControlText;           // 글자색을 시스템 기본색으로 변경함...
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            Thread socketworker = new Thread(new ThreadStart(socketThread));
            socketworker.IsBackground = true;
            socketworker.Start();
        }

        private void socketThread()
        {
            // 1. 데이타패킷 조합
            Debug.WriteLine("{0} : {1} : {2} : {3}", txtName.Text, txtSubject.Text, txtGrade.Text, txtMemo.Text);

            DataPacket packet = new DataPacket();

            packet.Name = txtName.Text;
            packet.Subject = txtSubject.Text;

            Int32 outNum;
            if (Int32.TryParse(txtGrade.Text, out outNum))
            {
                packet.Grade = Convert.ToInt32(txtGrade.Text);
            }
            else
            {
                packet.Grade = 0;
            }

            packet.Memo = txtMemo.Text;

            if (string.IsNullOrEmpty(packet.Name))
            {
                MessageBox.Show("[이 름]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtName.Focus();

                });
                return;
            }

            if (string.IsNullOrEmpty(packet.Subject))
            {
                MessageBox.Show("[과 목]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtSubject.Focus();

                });
                return;
            }

            if (packet.Grade == 0)
            {
                MessageBox.Show("[점 수]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtGrade.Focus();

                });
                return;
            }

            if (string.IsNullOrEmpty(packet.Memo))
            {
                packet.Memo = " ";
            }

            // 2. TcpClient 생성 및 설정
            TcpClient client = new TcpClient(txtServerIP.Text, Convert.ToInt32(txtServerPort.Text));
            NetworkStream stream = client.GetStream();
            updateStatusInfo("Connected");

            // 3. 전송하기
            byte[] buffer = packet.Serialize();

            stream.Write(buffer, 0, buffer.Length);
            updateStatusInfo(string.Format("{0} data sent", buffer.Length));

            // 4. 스트림과 소켓 닫기
            stream.Close();
            client.Close();

            // 5. listview 에 추가하기
            Invoke((MethodInvoker)delegate
            {
                int count = listView1.Items.Count;
                count++;

                ListViewItem i = new ListViewItem();
                i.Text = count.ToString();
                i.SubItems.Add(txtName.Text);
                i.SubItems.Add(txtSubject.Text);
                i.SubItems.Add(txtGrade.Text);
                i.SubItems.Add(txtMemo.Text);
                i.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                listView1.Items.Add(i);

                listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            });
        }

        private void updateStatusInfo(string content)
        {
            Action del = delegate()
            {
                lblStatus.Text = content;
            };
            Invoke(del);
        }

    }

posted by 따시쿵
2015. 1. 21. 16:37 C# with TCP/IP

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


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

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


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


프로그램 설명


클라이언트가 학생의 4가지 데이타(이름, 과목, 점수, 메모)를 서버로 전송한다고 가정하고 필요한 클래스는 아래와 같습니다. 메소드 Serialize(), Deserialize(ref byte[] data) 가 구조체에서 배열로, 배열에서 구조체로 변경해 주는 기능을 담당하고 있습니다.

DataPacket.cs


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    struct 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;

        // Calling this method will return a byte array with the contents
        // of the struct ready to be sent via the tcp socket.
        public byte[] Serialize()
        {
            // allocate a byte array for the struct data
            var buffer = new byte[Marshal.SizeOf(typeof(DataPacket))];

            // Allocate a GCHandle and get the array pointer
            var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            var pBuffer = gch.AddrOfPinnedObject();

            // copy data from struct to array and unpin the gc pointer
            Marshal.StructureToPtr(this, pBuffer, false);
            gch.Free();

            return buffer;
        }

        // this method will deserialize a byte array into the struct.
        public void Deserialize(ref byte[] data)
        {
            var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
            this = (DataPacket)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(DataPacket));
            gch.Free();
        }
    }


실행 후



메시지 전송 후



프로그램 작성 순서


1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.


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


2. 서버 프로그램


        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[1024];
                
                while (true)
                {
                    Console.WriteLine("Waiting for a connection.....");

                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("\nConnected!!");

                    NetworkStream stream = client.GetStream();

                    while (stream.Read(buffer, 0, buffer.Length) != 0)
                    {
                        // deserializing;
                        DataPacket packet = new DataPacket();
                        packet.Deserialize(ref buffer);

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


3. 클라이언트 프로그램


        static void Main(string[] args)
        {
            try 
            {
                string Name = string.Empty;
                string Subject = string.Empty;
                Int32 Grade = 0;
                string Memo = string.Empty;

                do
                {
                    // 1. 데이타 입력
                    Console.Write("이름 : ");
                    Name = Console.ReadLine();

                    Console.Write("과목 : ");
                    Subject = Console.ReadLine();

                    Console.Write("점수 : ");
                    string tmpGrage = Console.ReadLine();
                    if (tmpGrage != "")
                    {
                        int outGrade = 0;
                        if (Int32.TryParse(tmpGrage, out outGrade))
                            Grade = Convert.ToInt32(tmpGrage);
                        else
                            Grade = 0;
                    }
                    else
                        Grade = 0;

                    Console.Write("메모 : ");
                    Memo = Console.ReadLine();

                    if (string.IsNullOrEmpty(Name) || string.IsNullOrEmpty(Subject))
                        break;

                    // 2. 구조체 데이타를 바이트 배열로 변환
                    DataPacket packet = new DataPacket();
                    packet.Name = Name;
                    packet.Subject = Subject;
                    packet.Grade = Grade;
                    packet.Memo = Memo;

                    byte[] buffer = packet.Serialize();

                    // 3. 서버에 접속
                    TcpClient client = new TcpClient();
                    client.Connect("192.168.0.12", 13000);
                    Console.WriteLine("Connected...");

                    NetworkStream stream = client.GetStream();

                    // 4. 데이타 전송
                    stream.Write(buffer, 0, buffer.Length);
                    Console.WriteLine("{0} data sent", buffer.Length);
                    Console.WriteLine("===============================\n");

                    // 5. 스트림&소켓 닫기
                    stream.Close();
                    client.Close();

                } while (Name != "" && Subject != "");
            }
            catch (SocketException se)
            {
                Console.WriteLine("SocketException : {0} ", se.Message.ToString());
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception : {0} ", ex.Message.ToString());
            }
            Console.ReadLine();
        }

posted by 따시쿵
2015. 1. 20. 10:33 C# with TCP/IP

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


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

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


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


프로그램 설명


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


클라스 파일은 DataPacket.cs 파일입니다.

DataPacket.cs


    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;
using System.Runtime.InteropServices;


2. 서버 프로그램


        TcpListener server = null;            
        public MainForm()
        {
            InitializeComponent();
            FormClosing += new FormClosingEventHandler(WindowsFormClosing);
            InitStart();
        }

        private void WindowsFormClosing(object sender, FormClosingEventArgs s)
        {
            if (server != null)
                server = null;

            Application.Exit();
        }
        private void InitStart()
        {
            Thread socketworker = new Thread(new ThreadStart(socketThread));
            socketworker.IsBackground = true;
            socketworker.Start();
        }

        private void socketThread()
        {
            try
            {
                server = new TcpListener(IPAddress.Parse("192.168.0.12"), 13000);
                server.Start();

                while(true)
                { 
                    TcpClient client = server.AcceptTcpClient();
                    updateStatusInfo("Connected");
                    Thread clientworker = new Thread(new ParameterizedThreadStart(clientThread));
                    clientworker.IsBackground = true;
                    clientworker.Start(client);
                }              

            }
            catch(SocketException se)
            {
                Debug.WriteLine("SocketException : {0}", se.Message);
            }
            catch(Exception ex)
            {
                Debug.WriteLine("Exception : {0}", ex.Message);
            }
        }

        private void clientThread(object sender)
        {
            // 1. 데이타 받기
            TcpClient client = sender as TcpClient;
            NetworkStream stream = client.GetStream();

            byte[] buffer = new byte[8092];
            DataPacket packet = new DataPacket();

            while (stream.Read(buffer, 0, Marshal.SizeOf(packet)) != 0)
            {
                unsafe
                {
                    fixed (byte* fixed_buffer = buffer)
                    {
                        Marshal.PtrToStructure((IntPtr)fixed_buffer, packet);
                    }
                }
            }

            stream.Close();
            client.Close();

            // 2. 데이타 표시하기
            string Name = packet.Name;
            string Subject = packet.Subject;
            Int32 Grade = packet.Grade;
            string Memo = packet.Memo;

            Debug.WriteLine("{0} : {1} : {2} : {3}", Name, Subject, Grade, Memo);

            Invoke((MethodInvoker)delegate
            {
                int count = listView1.Items.Count;
                count++;

                ListViewItem i = new ListViewItem();
                i.Text = count.ToString();
                i.SubItems.Add(Name);
                i.SubItems.Add(Subject);
                i.SubItems.Add(Grade.ToString());
                i.SubItems.Add(Memo);
                i.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                listView1.Items.Add(i);

                listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            });

            // 3. 상태값 표시하기
            updateStatusInfo("Data Accepted");
        }

        private void updateStatusInfo(string content)
        {
            Action del = delegate()
            {
                lblStatus.Text = content;
            };
            Invoke(del);
        }

        private void btnDataClear_Click(object sender, EventArgs e)
        {
            if(MessageBox.Show("데이타를 모두 삭제 하시겠습니까?","질문", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK)
            {
                listView1.Items.Clear();
            }
        }


3. 클라이언트 프로그램


        public MainForm()
        {
            InitializeComponent();

            btnSend.MouseEnter += new EventHandler(btnSend_MouseEnter);
            btnSend.MouseLeave += new EventHandler(btnSend_MouseLeave);
        }

        void btnSend_MouseEnter(object sender, EventArgs e)
        {
            btnSend.UseVisualStyleBackColor = false;
            btnSend.BackColor = Color.FromArgb(255, 255, 165, 00);  // 배경색을 오렌지 색으로 변경함...
            btnSend.ForeColor = Color.White;                        // 글자색을 흰색으로 변경함
        }

        void btnSend_MouseLeave(object sender, EventArgs e)
        {
            btnSend.UseVisualStyleBackColor = true;
            btnSend.BackColor = SystemColors.Control;               // 배경색을 시스템 기본색으로 변경함...
            btnSend.ForeColor = SystemColors.ControlText;           // 글자색을 시스템 기본색으로 변경함...
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            Thread socketworker = new Thread(new ThreadStart(socketThread));
            socketworker.IsBackground = true;
            socketworker.Start();
        }

        private void socketThread()
        {
            // 1. 데이타패킷 조합
            Debug.WriteLine("{0} : {1} : {2} : {3}", txtName.Text, txtSubject.Text, txtGrade.Text, txtMemo.Text);

            DataPacket packet = new DataPacket();

            packet.Name = txtName.Text;
            packet.Subject = txtSubject.Text;

            Int32 outNum;
            if(Int32.TryParse(txtGrade.Text, out outNum))
            {
                packet.Grade = Convert.ToInt32(txtGrade.Text);
            }
            else
            {
                packet.Grade = 0;
            }
            
            packet.Memo = txtMemo.Text;

            if (string.IsNullOrEmpty(packet.Name))
            {
                MessageBox.Show("[이 름]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtName.Focus();
                    
                });
                return;
            }

            if (string.IsNullOrEmpty(packet.Subject))
            {
                MessageBox.Show("[과 목]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtSubject.Focus();

                });
                return;
            }

            if (packet.Grade == 0)
            {
                MessageBox.Show("[점 수]을 입력하시기 바랍니다", "경고", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Invoke((MethodInvoker)delegate
                {
                    txtGrade.Focus();

                });
                return;
            }

            if (string.IsNullOrEmpty(packet.Memo))
            {
                packet.Memo = " ";
            }

            // 2. TcpClient 생성 및 설정
            TcpClient client = new TcpClient(txtServerIP.Text, Convert.ToInt32(txtServerPort.Text));
            NetworkStream stream = client.GetStream();
            updateStatusInfo("Connected");

            // 3. 전송하기
            byte[] buffer = new byte[Marshal.SizeOf(packet)];

            unsafe
            {
                fixed (byte* fixed_buffer = buffer)
                {
                    Marshal.StructureToPtr(packet, (IntPtr)fixed_buffer, false);
                }
            }

            stream.Write(buffer, 0, Marshal.SizeOf(packet));
            updateStatusInfo(string.Format("{0} data sent", Marshal.SizeOf(packet)));

            // 4. 스트림과 소켓 닫기
            stream.Close();
            client.Close();

            // 5. listview 에 추가하기
            Invoke((MethodInvoker)delegate
            {
                int count = listView1.Items.Count;
                count++;

                ListViewItem i = new ListViewItem();
                i.Text = count.ToString();
                i.SubItems.Add(txtName.Text);
                i.SubItems.Add(txtSubject.Text);
                i.SubItems.Add(txtGrade.Text);
                i.SubItems.Add(txtMemo.Text);
                i.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                listView1.Items.Add(i);

                listView1.Items[this.listView1.Items.Count - 1].EnsureVisible();
            });
        }

        private void updateStatusInfo(string content)
        {
            Action del = delegate()
            {
                lblStatus.Text = content;
            };
            Invoke(del);
        }

posted by 따시쿵
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 따시쿵
2015. 1. 15. 16:59 C#

Windows Forms의 컨트롤은 특정 스레드에 바인딩되며 스레드로부터 안전하지 않습니다. 따라서 다른 스레드에서 컨트롤의 메서드를 호출할 경우 해당 컨트롤의 호출 메서드 중 하나를 사용하여 호출을 적절한 스레드에 마샬링해야 합니다. 이 속성을 사용하면 호출 메서드를 호출해야 하는지 여부를 확인할 수 있습니다. 이 방법은 컨트롤을 소유한 스레드를 알 수 없는 경우 유용합니다.


컨트롤의 핸들이 없으면 InvokeRequired는 창 핸들이 있는 컨트롤이나 폼을 찾을 때까지 해당 컨트롤의 부모 체인을 위로 검색합니다. 적절한 핸들을 찾을 수 없으면InvokeRequired 메서드는 false를 반환합니다.


즉, 동일한 스레드에서 호출이 발생하여 Invoke가 필요하지 않거나 다른 스레드에서 컨트롤이 만들어졌지만 컨트롤의 핸들은 아직 만들어지지 않은 경우 InvokeRequired는false를 반환할 수 있습니다.

컨트롤의 핸들이 아직 만들어지지 않은 경우 컨트롤에 대한 속성, 메서드 또는 이벤트를 호출해서는 안 됩니다. 이렇게 하면 배경 스레드에서 컨트롤의 핸들이 만들어져 메시지 펌프 없이 스레드에서 컨트롤이 격리되고 응용 프로그램이 불안정해질 수 있습니다.


InvokeRequired 가 배경 스레드에서 false를 반환하면 IsHandleCreated 값을 확인하여 이러한 상황을 방지할 수도 있습니다. 컨트롤 핸들이 아직 만들어지지 않은 경우 핸들이 만들어질 때까지 기다린 후 Invoke 또는 BeginInvoke를 호출해야 합니다. 일반적으로 이러한 경우는 폼이 표시되기 전이나 Application.Run이 호출되기 전의Application.Run(new MainForm())에서와 같이 응용 프로그램의 기본 폼 생성자에서 배경 스레드가 만들어지는 경우에만 발생합니다.


다음은 멀티쓰레드간에 사용할 수 있는 몇가지 예제를 보여 줍니다.


1. 컨트롤의 InvokeRequired 속성을 이용하는 경우


if (listBox1.InvokeRequired)
{
    listBox1.BeginInvoke(new MethodInvoker(delegate
    {
        listBox1.Items.Add(content);
    }));
}
else
    listBox1.Items.Add(content);

}


2. Action 과 Invoke method를 이용하는 경우


Action del = delegate()
            {
                textBox1.AppendText(s + System.Environment.NewLine);
            };
Invoke(del);


3. Invoke method 와 무명메소드를 이용하는 경우


Invoke((MethodInvoker)delegate
{
    textBox1.AppendText(s + System.Environment.NewLine);
});


4. Invoke method와 EventHanlder 를 이용하는 경우

private void Form1_Load(object sender, EventArgs e)
{
     new Thread(delegate()
         {
             this.Invoke(new EventHandler(displaytext));                    
          }).Start();
}

private void displaytext(object sender, EventArgs e)
{
    richTextBox1.Text = "메시지 출력하기";
}


'C#' 카테고리의 다른 글

텍스트 로그 파일 라이브러리 - 2  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
Task 클래스  (0) 2015.01.10
텍스트 로그 파일 라이브러리 - 1  (0) 2015.01.09
ManualResetEvent 클래스  (0) 2014.12.24
posted by 따시쿵
2015. 1. 15. 16:29 C# with TCP/IP

프로그램 설명


서버와 클라이언트를 각각 쓰레드를 이용한 멀티프로그램으로 예제를 만들어 보았습니다.


실행 후



메시지 전송 후



프로그램 작성 순서


1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.

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

2. 서버 프로그램

        private void btnStart_Click(object sender, EventArgs e)
        {
            Thread tcpServerRunThread = new Thread(new ThreadStart(TcpServerRun));
            tcpServerRunThread.IsBackground = true;
            tcpServerRunThread.Start();
        }

        private void TcpServerRun()
        {
            TcpListener tcpListener = new TcpListener(IPAddress.Any, 5004);
            tcpListener.Start();
            updateUI("Listening");
            updateUI("===========================================");

            while(true)
            {
                TcpClient client = tcpListener.AcceptTcpClient();
                updateUI("Connected");
                Thread tcpHandlerThread = new Thread(new ParameterizedThreadStart(tcpHandler));
                tcpHandlerThread.Start(client);
            }
        }

        private void tcpHandler(object client)
        {
            TcpClient mClient = client as TcpClient;
            NetworkStream stream = mClient.GetStream();
            byte[] message = new byte[1024];
            int byteRead = stream.Read(message, 0, message.Length);
            updateUI("New Message = " + Encoding.UTF8.GetString(message, 0, byteRead));
            updateUI("");

            stream.Close();
            mClient.Close();
        }

        private void updateUI(string s)
        {
            Action del = delegate()
            {
                textBox1.AppendText(s + System.Environment.NewLine);
            };
            Invoke(del);
        }

3. 클라이언트 프로그램

        private void btnSend_Click(object sender, EventArgs e)
        {
            Thread mThread = new Thread(new ThreadStart(SendAsClient));
            mThread.Start();
        }

        private void SendAsClient()
        {
            TcpClient client = new TcpClient();
            client.Connect(IPAddress.Parse(textServerIP.Text), Convert.ToInt32(textServerPort.Text));
            updateUI("Connected");

            NetworkStream stream = client.GetStream();

            string sendData = textMessage.Text;
            byte[] msg = new byte[256];
            msg = Encoding.UTF8.GetBytes(sendData);

            stream.Write(msg, 0, msg.Length);
            updateUI(string.Format("send data : {0}", sendData));
            updateUI(string.Format("{0} bytes sent", msg.Length ));

            stream.Close();
            client.Close();
        }

        private void updateUI(string s)
        {
            Func<int> del = delegate()
            {
                textBox1.AppendText(s + System.Environment.NewLine);
                return 0;
            };
            Invoke(del);
        }


posted by 따시쿵
2015. 1. 13. 16:16 C# with TCP/IP

프로그램 설명


msdn 에 있는 예제를 가지고 만든 버전입니다.


TcpListener 클래스 

http://msdn.microsoft.com/ko-kr/library/system.net.sockets.tcplistener(v=vs.110).aspx


TcpClient 클래스

http://msdn.microsoft.com/ko-kr/library/system.net.sockets.tcpclient(v=vs.110).aspx


클라이언트 버전은 사용자 입력을 반복적으로 입력받을 수 있게 수정했습니다.


클라이언트의 메시지를 서버가 받아서 대문자로 변경해 주는 작업만 처리합니다.



실행 후



메시지 전송 후




프로그램 작성 순서


1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.

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


2. 서버 프로그램

        TcpListener server = null;
 
        public MainForm()
        {
            InitializeComponent();
            FormClosing += new FormClosingEventHandler(Form_Closing);
        }

        private void Form_Closing(object sender, FormClosingEventArgs e)
        {
            if (server != null)
                server = null;

            Application.Exit();
        }
        
        private void btnListen_Click(object sender, EventArgs e)
        {
            new Thread(delegate()
                {
                    try
                    {
                        // Set the TcpListener on port 14000.
                        Int32 port = 14000;
                        IPAddress localAddr = IPAddress.Parse("127.0.0.1");

                        // TcpListener server = new TcpListener(port);
                        server = new TcpListener(localAddr, port);
                        server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                        // Start listening for client requests.
                        server.Start();

                        // Buffer for reading data
                        Byte[] bytes = new Byte[256];
                        String data = null;
                        
                        // Enter the listening loop.
                        while (true)
                        {
                            Invoke((MethodInvoker)delegate
                            {
                                listBox1.Items.Add("Waiting for a connection... ");
                            });

                            // Perform a blocking call to accept requests.
                            // You could also user server.AcceptSocket() here.
                            TcpClient client = server.AcceptTcpClient();
                            Invoke((MethodInvoker)delegate
                            {
                                listBox1.Items.Add("Connected!");
                            });

                            data = null;

                            // Get a stream object for reading and writing
                            NetworkStream stream = client.GetStream();

                            int i;

                            // Loop to receive all the data sent by the client.
                            while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                            {
                                // Translate data bytes to a ASCII string.
                                data = System.Text.Encoding.UTF8.GetString(bytes, 0, i);
                                Invoke((MethodInvoker)delegate
                                {
                                    listBox1.Items.Add(string.Format("Received: {0}", data));
                                });

                                // Process the data sent by the client.
                                data = data.ToUpper();

                                byte[] msg = System.Text.Encoding.UTF8.GetBytes(data);

                                // Send back a response.
                                stream.Write(msg, 0, msg.Length);
                                Invoke((MethodInvoker)delegate
                                {
                                    listBox1.Items.Add(string.Format("Sent: {0}", data));
                                    listBox1.Items.Add("");
                                });
                            }

                            // Shutdown and end connection
                            client.Close();
                        }  // end of outer while                    
                    }
                    catch (SocketException se)
                    {
                        MessageBox.Show(string.Format("SocketException: {0}", se.Message.ToString()));
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format("Exception: {0}", ex.Message.ToString()));
                    }
                    finally
                    {
                        // Stop listening for new clients.
                        server.Stop();
                    }
            }).Start();
        }

2. 클라이언트 프로그램


        private void btnSend_Click(object sender, EventArgs e)
        {
            string serverIP = textServerIP.Text;
            string sendData = textMessage.Text;

            SendMessage(serverIP, sendData);
        }

        private void SendMessage(string server, string message)
        {
            try
            {
                // Create a TcpClient.
                // Note, for this client to work you need to have a TcpServer 
                // connected to the same address as specified by the server, port
                // combination.
                Int32 port = 14000;
                TcpClient client = new TcpClient(server, port);

                // Translate the passed message into ASCII and store it as a Byte array.
                Byte[] data = System.Text.Encoding.UTF8.GetBytes(message);

                // Get a client stream for reading and writing.
                //  Stream stream = client.GetStream();

                NetworkStream stream = client.GetStream();

                // Send the message to the connected TcpServer. 
                stream.Write(data, 0, data.Length);

                Invoke((MethodInvoker)delegate
                {
                    listBox1.Items.Add(string.Format("Sent: {0}", message));
                });

                // Receive the TcpServer.response.

                // Buffer to store the response bytes.
                data = new Byte[256];

                // String to store the response ASCII representation.
                String responseData = String.Empty;

                // Read the first batch of the TcpServer response bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.UTF8.GetString(data, 0, bytes);
                Invoke((MethodInvoker)delegate
                {
                    listBox1.Items.Add(string.Format("Received: {0}", responseData));
                    listBox1.Items.Add("");
                });

                // Close everything.
                stream.Close();
                client.Close();
            }
            catch (ArgumentNullException e)
            {
                MessageBox.Show(string.Format("ArgumentNullException: {0}", e.Message.ToString()));
            }
            catch (SocketException e)
            {
                MessageBox.Show(string.Format("SocketException: {0}", e.Message.ToString()));
            }
        }
posted by 따시쿵