블로그 이미지
따시쿵

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 31

Notice

2014. 12. 23. 11:52 C# with TCP/IP

프로그램 설명


클라이언트가 보낸 데이타의 양이 많아서 한 번에 받을 수가 없는 경우가 있습니다. 보낸 데이타를 손실없이 모두 다 받는 방법을 설명합니다.


프로그램 구조의 핵심은 클라이언트가 데이타를 보낼때에 전송 데이타 사이즈를 미리 전송하고, 두 번째로 실제 데이타를 존송합니다.


서버에서는 전송된 데이타 사이즈를 미리 받아서 받을 버퍼 사이즈 크기를 결정하고, 받을 데이타가 모두 전송 될 때까지 루프를 돌면서 메모리 스트림에 기록을 한 후에, 화면에 보여줄 때에 한꺼번에 가져와서 화면에 보여 줍니다.


accept 소켓의 ReceiveBufferSize 속성 값이 65536 (int) 이니 일반적인 텍스트를 주고 받는 데에는 별무리가 없을 것으로 보이고, 단지 파일를 전송할때에는 영향을 받을 것으로 보입니다.


예제는 상당히 긴 텍스트를 전송하기는 것을 시나리오로 작성했습니다.


실행 후





메시지 전송 후







프로그램 작성 순서


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

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


2. 서버 프로그램

        Socket sck;
        Socket acc;

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sck.Bind(new IPEndPoint(0, 8));
            sck.Listen(0);

            acc = sck.Accept();

            sck.Close();

            new Thread(() =>
            {
                while(true)
                {
                    try
                    {
                        byte[] sizeBuf = new byte[4];

                        acc.Receive(sizeBuf, 0, sizeBuf.Length, 0);

                        int size = BitConverter.ToInt32(sizeBuf, 0);
                        MemoryStream ms = new MemoryStream();

                        while (size > 0)
                        {
                            byte[] buffer;
                            if (size < acc.ReceiveBufferSize)
                                buffer = new byte[size];
                            else
                                buffer = new byte[acc.ReceiveBufferSize];

                            int rec = acc.Receive(buffer, 0, buffer.Length, 0);

                            size -= rec;

                            ms.Write(buffer, 0, buffer.Length);
                        }

                        ms.Close();

                        byte[] data = ms.ToArray();

                        ms.Dispose();

                        Invoke((MethodInvoker)delegate
                        {
                            richTextBox1.Text = Encoding.UTF8.GetString(data);
                        });
                    }
                    catch
                    {
                        MessageBox.Show("서버: DISCONNECTION!");
                        acc.Close();
                        acc.Dispose();
                        break;
                    }
                }
                Application.Exit();
            }).Start();
        }
    }


3. 클라이언트 프로그램

        Socket sck;
        public MainForm()
        {
            InitializeComponent();
            FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (sck.Connected)
                sck.Close();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                sck.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8));
            }
            catch
            {
                MessageBox.Show("Unable to connect!");
            }
        }

        private void btnSendText_Click(object sender, EventArgs e)
        {
            byte[] data = Encoding.UTF8.GetBytes(richTextBox1.Text);

            sck.Send(BitConverter.GetBytes(data.Length), 0, 4, 0);
            sck.Send(data);
        }

posted by 따시쿵
2014. 12. 23. 11:51 C# with TCP/IP

프로그램 설명


클라이언트가 연결을 끊을 시에 서버에서 인지를 하고 서버 프로그램도 같이 종료되는 프로그램입니다. 

윈도우 폼 형식으로 작성을 했으며, 실제 테스트를 하기 위해서는 클라이언트 프로그램을 실행하고 메시지를 주고 받은 후, 팝업 창의 X 버튼을 눌러서 프로그램을 종료하는 것으로 합니다.


확인을 위해서 각 단계별로 메시지를 보여 주었습니다.


실행 후





메시지 전송 후





프로그램 작성 순서


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

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


2. 서버 프로그램

        Socket sock;
        Socket acc;

        public MainForm()
        {
            InitializeComponent();
        }

        Socket socket()
        {
            return new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            sock = socket();

            sock.Bind(new IPEndPoint(0, 3));
            sock.Listen(0);

            new Thread(delegate()
            {
                acc = sock.Accept();
                MessageBox.Show("서버: CONNECTION ACCEPTED!");
                sock.Close();

                while(true)
                {
                    try
                    {
                        byte[] buffer = new byte[255];
                        int rec = acc.Receive(buffer, 0, buffer.Length, SocketFlags.None);

                        if (rec <= 0)
                        {
                            throw new SocketException();
                        }

                        Array.Resize(ref buffer, rec);

                        Invoke((MethodInvoker)delegate
                        {
                            listBox1.Items.Add(Encoding.UTF8.GetString(buffer));
                        });

                    }
                    catch 
                    {
                        MessageBox.Show("서버: DISCONNECTION!");
                        acc.Close();
                        acc.Dispose();
                        break;
                    }
                }
                Application.Exit();
            }).Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] data = Encoding.UTF8.GetBytes(textBox1.Text);
                acc.Send(data, 0, data.Length, 0);
            }
            catch(SocketException ex) {
                MessageBox.Show(ex.Message.ToString());
            }
        }

3. 클라이언트 프로그램

        Socket sock;
        public MainForm()
        {
            InitializeComponent();
            sock = socket();
            FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
        }

        void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            sock.Close();
        }

        Socket socket()
        {
            return new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        void read()
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[255];
                    int rec = sock.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                    
                    if (rec <= 0)
                    {
                        throw new SocketException();
                    }

                    Array.Resize(ref buffer, rec);

                    Invoke((MethodInvoker)delegate
                    {
                        listBox1.Items.Add(Encoding.UTF8.GetString(buffer));
                    });
                }
                catch {
                    MessageBox.Show("클라이언트: DISCONNECTION");
                    sock.Close();
                    break;                    
                }
            }
            Application.Exit();
        }

        private void btn_connect_Click(object sender, EventArgs e)
        {
            try { 
                sock.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text), 3));
                new Thread(() =>
                    {
                        read();
                    }).Start();
            }
            catch
            {
                MessageBox.Show("클라이언트: CONNECTION FAILED!");
            }
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            byte[] data = Encoding.UTF8.GetBytes(textBox2.Text);
            sock.Send(data, 0, data.Length, SocketFlags.None);
        }

posted by 따시쿵
2014. 12. 23. 11:51 C# with TCP/IP

프로그램 설명


서버가 listen 상태에서 클라이언트로부터 접속이 이루어지면 "hello Client" 메시지를 클라이언트에 전송하고, 클라이언트로부터 전송 된 메시지를 화면에 출력합니다.


클라이언트는 서버에 접속 한 후 사용자의 입력을 기달리는 프롬프트를 화면에 출력하고, 사용자가 입력하는 메시지를 서버에 전송하고 서버로부터 받은 받은 메시지 "hello Client" 화면에 보여줍니다.



실행 후




메시지 전송 후




프로그램 작성 순서


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

using System.Net;
using System.Net.Sockets;
2. 서버 프로그램

            Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sck.Bind(new IPEndPoint(0, 1994));
            sck.Listen(0);

            Socket acc = sck.Accept();

            byte[] buffer = Encoding.UTF8.GetBytes("Hello Client");
            acc.Send(buffer, 0, buffer.Length, SocketFlags.None);

            buffer = new byte[acc.SendBufferSize];
            int rec = acc.Receive(buffer, 0, buffer.Length, SocketFlags.None);
            
            Array.Resize(ref buffer, rec);

            Console.WriteLine("Received: {0}", Encoding.UTF8.GetString(buffer));

            sck.Close();
            acc.Close();

            Console.Read();
3. 클라이언트 프로그램

            Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1994);
            sck.Connect(endPoint);

            Console.Write("Enter Message: ");
            string msg = Console.ReadLine();
            byte[] msgBuffer = Encoding.UTF8.GetBytes(msg);
            sck.Send(msgBuffer, 0, msgBuffer.Length, SocketFlags.None);

            byte[] buffer = new byte[255];
            int rec = sck.Receive(buffer, 0, buffer.Length, SocketFlags.None);

            Array.Resize(ref buffer, rec);

            Console.WriteLine("Recevied: {0}", Encoding.UTF8.GetString(buffer));

            Console.Read();


posted by 따시쿵
2014. 12. 23. 11:51 C# with TCP/IP

Berkeley 소켓 인터페이스를 이용한 구현을 예제로 만듭니다. 서버와 클라이언트는 모두 콘솔 프로그램으로 만들며, 지금 작성하는 프로그램은 가장 간단한 프로그램으로 클라이언트가 서버로 메시지를 한 번만 전송하고 콘솔 화면에서 엔터키를 입력함으로 프로그램이 종료되는 것입니다.


프로그램 설명


서버는 소켓을 생성하고 Bind 시키며 Listen 상태인 대기 상태로 둡니다. 클라이언트의 연결 요청이 들어오면 accept 소켓을 생성하고 데이타를 받기 시작합니다. 받은 데이타는 콘솔 화면에 보여주고 사용자가 엔터키를 입력함으로 프로그램은 종료 됩니다.


클라이언트는 서버에 아이피와 포트를 이용해서 연결을 하고 콘솔에 텍스트를 입력하고 엔터 키를 입력함으로 서버에 데이타를 전송하고, 데이타가 전송이 되었다는 메시지를 보이고, 사용자가 엔터키를 입력함으로 프로그램이 종료 됩니다.


실행 후



메시지 전송 후



프로그램 작성 순서


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

using System.Net;
using System.Net.Sockets;

2. 서버에  아래의 코드를 입력합니다.


        static byte[] Buffer { get; set; }
        static Socket sck;

        static void Main(string[] args)
        {
            sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sck.Bind(new IPEndPoint(IPAddress.Any, 1234));
            sck.Listen(100);

            Socket accepted = sck.Accept();

            Buffer = new byte[accepted.SendBufferSize];
            int bytesRead = accepted.Receive(Buffer);
            byte[] formatted = new byte[bytesRead];
            for (int i = 0; i< bytesRead; ++i)
            {
                formatted[i] = Buffer[i];
            }

            string strdata = Encoding.UTF8.GetString(formatted);
            Console.Write(strdata + "\r\n");
            Console.Read();

            accepted.Close();
            sck.Close();
        }



3. 클라이언트에 아래의 코드를 입력합니다.

        static Socket sck;
        static void Main(string[] args)
        {
            sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234);

            try
            {
                sck.Connect(localEndPoint);
            }
            catch 
            {
                Console.Write("Unable to connect to remote end point!\r\n");
                Main(args);
            }

            Console.Write("Enter Text: ");
            string text = Console.ReadLine();
            byte[] data = Encoding.UTF8.GetBytes(text);

            sck.Send(data);
            Console.Write("Data Sent!\r\n");
            Console.Write("Press any key To continue...");
            Console.Read();
            sck.Close();
        }

posted by 따시쿵
2014. 12. 23. 11:51 C# with TCP/IP




'C# with TCP/IP' 카테고리의 다른 글

[Program C#]Socket 통신 - 기본  (1) 2014.12.23
[Program C#]Socket 통신 - 예제  (0) 2014.12.23
응용 프로토콜 - 비연결/연결  (0) 2014.12.22
Socket의 세 가지 형태  (0) 2014.12.20
Transport 계층 프로토콜 포트  (0) 2014.12.19
posted by 따시쿵
2014. 12. 22. 14:32 C# with TCP/IP




'C# with TCP/IP' 카테고리의 다른 글

[Program C#]Socket 통신 - 예제  (0) 2014.12.23
Socket 시스템 호출 명령  (0) 2014.12.23
Socket의 세 가지 형태  (0) 2014.12.20
Transport 계층 프로토콜 포트  (0) 2014.12.19
Transport Layer – UDP  (0) 2014.12.18
posted by 따시쿵
2014. 12. 20. 08:52 C# with TCP/IP




'C# with TCP/IP' 카테고리의 다른 글

Socket 시스템 호출 명령  (0) 2014.12.23
응용 프로토콜 - 비연결/연결  (0) 2014.12.22
Transport 계층 프로토콜 포트  (0) 2014.12.19
Transport Layer – UDP  (0) 2014.12.18
Transport Layer – TCP  (0) 2014.12.17
posted by 따시쿵
2014. 12. 19. 10:39 C# with TCP/IP



'C# with TCP/IP' 카테고리의 다른 글

응용 프로토콜 - 비연결/연결  (0) 2014.12.22
Socket의 세 가지 형태  (0) 2014.12.20
Transport Layer – UDP  (0) 2014.12.18
Transport Layer – TCP  (0) 2014.12.17
Transport Layer – TCP & UDP  (0) 2014.12.16
posted by 따시쿵
2014. 12. 18. 16:40 C# with TCP/IP




'C# with TCP/IP' 카테고리의 다른 글

Socket의 세 가지 형태  (0) 2014.12.20
Transport 계층 프로토콜 포트  (0) 2014.12.19
Transport Layer – TCP  (0) 2014.12.17
Transport Layer – TCP & UDP  (0) 2014.12.16
Internet Protocol Routing  (0) 2014.12.15
posted by 따시쿵
2014. 12. 17. 12:41 C# with TCP/IP









'C# with TCP/IP' 카테고리의 다른 글

Transport 계층 프로토콜 포트  (0) 2014.12.19
Transport Layer – UDP  (0) 2014.12.18
Transport Layer – TCP & UDP  (0) 2014.12.16
Internet Protocol Routing  (0) 2014.12.15
Internet Protocol Header 구성 요소  (0) 2014.12.13
posted by 따시쿵