[C# 윈폼] 윈폼 TCP/IP 통신 프로그램 클라이언트 프로그램 개발하기

안녕하세요.

 

오늘은 윈폼으로 TCP/IP 통신 프로그램 만들기 2번째 시간으로써, 지난번에 먼저 서버 프로그램을 개발하였고 오늘은 서버와 통신을 해서 메시지를 보낼 클라이언트 프로그램을 개발하는 방법에 대해서 글을 쓰려고 합니다.

 

먼저 이전 포스팅을 보고 오지 않으신 분들은 아래 링크로 연결된 곳에 먼저 가셔서 서버 프로그램을 한번 따라서 만들어 보시는 걸 추천 드리겠습니다.

 

그럼 바로 클라이언트 프로그램을 어떻게 구현하는지 예제를 통해서 보여 드리도록 하겠습니다.

 

먼저 클라이언트 UI 구성은 다음과 같습니다.

 

클라이언트 UI 구성

 

위와 같이 클라이언트 프로그램 UI를 구성하였습니다.

 

저는 MetroDesign을 이용하여 프로그램을 만들었지만, MetroDesign을 이용해서 개발할 필요는 없기 때문에 그냥 일반 윈폼 컨트롤을 이용하여 위와 같이 UI를 구성해도 문제가 없습니다.

 

그럼 이제 클라이언트에서 서버 접속 요청을 하면 서버에서 해당 클라이언트의 접속을 받아서 ListBox에 해당 내용을 출력하고, 메시지까지 서버로 보내는 내용을 예제 코드로 작성해 보도록 하겠습니다.

 

예제 코드
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace Client
{
    public partial class Client : MetroFramework.Forms.MetroForm
    {
        public static string data = null;
 
        //서버가 접속할 소켓에서 listen accept 할 변수
        private Socket listener = null;
        private Socket handler = null;
 
        // Data buffer from incoming data
        private byte[] bytes = new byte[1024];
 
        public Client()
        {
            InitializeComponent();
            FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
        }
 
        public void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (handler != null)
            {
                handler.Close();
                handler.Dispose();
            }
            if (listener != null)
            {
                listener.Close();
                listener.Dispose();
            }
 
            Application.Exit();
        }
 
        /// <summary>
        /// Local IP 반환해주는 메서드
        /// </summary>
        /// <returns></returns>
        public static string LocalIPAddress()
        {
            IPHostEntry host;
            string localIP = "";
            host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    localIP = ip.ToString();
                    return localIP;
                }
            }
            return "127.0.0.1";
        }
 
        public static string TruncateLeft(string value, int maxLength)
        {
            if (string.IsNullOrEmpty(value)) return value;
            return value.Length <= maxLength ? value : value.Substring(0, maxLength);
        }
 
        /// <summary>
        /// 서버 접속 요청 대기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mt_Server_Listen_Click(object sender, EventArgs e)
        {
            new Thread(delegate ()
            {
                // Establish the local endpoint for the socket
                // Dns.GetHostName returns the name of the
                // host running the application
                IPAddress localIPAddress = IPAddress.Parse(LocalIPAddress());
                IPEndPoint localEndPoint = new IPEndPoint(localIPAddress, 12000);
 
                // Create a TCP/IP Socket
                listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
 
                // Bind the socket to the local endpoint and
                // listen for incoming connections.
                try
                {
                    new Thread(delegate ()
                    {
                        listener.Bind(localEndPoint);
                        listener.Listen(10);
 
                        // Start listening for connections.
                        while (true)
                        {
                                Invoke((MethodInvoker)delegate
                                {
                                    lb_SendMsg.Items.Add("Waiting for connections.....");
                                });
 
                                // Program is suspended while waiting for an incoming connection.
                                handler = listener.Accept();
                                Invoke((MethodInvoker)delegate
                                {
                                    lb_SendMsg.Items.Add("클라이언트 연결.....OK");
                                });
                            
                        }
                    }).Start();
                }
                catch (SocketException se)
                {
                    MessageBox.Show("SocketException 에러 : " + se.ToString());
                    switch (se.SocketErrorCode)
                    {
                        case SocketError.ConnectionAborted:
                        case SocketError.ConnectionReset:
                            handler.Shutdown(SocketShutdown.Both);
                            handler.Close();
                            break;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Exception 에러 : " + ex.ToString());
                }
            }).Start();
        }
 
        /// <summary>
        /// 서버랑 연결 완료 후 메시지 보내기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_sendMsg_Click(object sender, EventArgs e)
        {
            string data = null;
 
            try
            {
                // 서버에게 보낼 메시지를 byte 배열로 이용해서 Encoding 해준다.
                byte[] msg = Encoding.UTF8.GetBytes(tb_sendMsg.Text + "<eof>");
                int bytesSent = handler.Send(msg);
 
                //bytes = null;
                int bytesRec = handler.Receive(bytes);
                //int bytesRec = 0;
 
                if (bytesSent <= 0)
                {
                    throw new SocketException();
                }
 
                //Client에서 보낸 메시지를 Server에서 받고 Server가 다시 바로 Client에게 받은 메시지를 그대로 Send한다.
                data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
 
                Invoke((MethodInvoker)delegate
                {
                    //listBox1.Items.Add(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
                    lb_SendMsg.Items.Add(data);
                });
 
            }
            catch (SocketException se)
            {
                MessageBox.Show("SocketException = " + se.Message.ToString());
                handler.Close();
                handler.Dispose();
            }
            catch (NullReferenceException ne)
            {
                MessageBox.Show("현재 클라이언트와 서버가 연결되지 않았습니다.");
            }
        }
    }
}
 
cs

 

실행 결과

 

위와 같이 클라이언트에서 서버로 접속 요청을 하면, 서버는 해당 클라이언트의 IP를 확인하여 본인이 가지고 있는 IP가 맞다면 접속 승인을 하고 통신이 가능한 것을 확인하실 수 있습니다.

 

감사합니다.^^

728x90

이 글을 공유하기

댓글(3)

  • 2021.05.12 19:51 신고

    서버에도 연결 성공이라고 나오고
    클라이언트도 연결 OK라 나오는데
    글을 적어서 Send 버튼을 누르면 프로그램이 응답 없음 되면서 죽어버리는데 무슨 문제일까요?ㅠㅠ

    • 2021.05.12 22:06 신고

      왜인지 모르겠지만 이제는 되네요...
      <eof>를 ,eof>라고 오타냈던게 문제가 아니었을까 하는 생각이 드네요ㅜ

      클라이언트도 연결중 창을 닫으니 서버랑 같은 오류창이 뜨는것같아요!
      서로 연결돼있는것중에 먼저 창 닫는쪽은 오류창이 뜨고
      다른 하나는 연결이 끊겨서 그런지 창 닫을 떄 오류창이 안뜨네욤.

    • 2021.05.13 07:23 신고

      해결하셨다니 다행이네요ㅎㅎ 저 프로그램이 제가 학생때 그냥 공부용으로 막 짰던거라..잔 오류들이 많을거에요ㅜㅜ 그냥 정리차 블로그에 올렸던거라서요..그래도 ThumbKing 님께서 스스로 해결하셨다니 멋있습니다ㅎㅎ 앞으론 저도 포스팅 쓸땐 좀 더 자세히 글 써볼게요ㅎㅎ

Designed by JB FACTORY