프로그램 설명
msdn 사이트에 있는 예제를 조금 수정해서 작성했습니다.
원본 소스는 아래와 같습니다.
비동기 서버 예제 : http://msdn.microsoft.com/ko-kr/library/bew39x2a(v=vs.110).aspx
비동기 클라이언트 예제 : http://msdn.microsoft.com/ko-kr/library/fx6588te(v=vs.110).aspx
윈도우 버전으로 변경하는 중에 서버 소스는 변경할 부분이 별로 없지만 클라이언트 소스는 문제가 여러가지 발생하여 기본 골격을 변경했습니다.
클라이언트 소스에 나오는 부분을 client class 를 만들어 따로 저장 했으며, 화면 부분은 delegate 를 이용해서 진행 상황의 데이타를 보여 주는 구조를 가지고 있습니다.
client.cs 는 첨부 파일로 올려 놓습니다.
실행 후
메시지 전송 후
프로그램 작성 순서
1. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.
1 2 3 | using System.Net; using System.Net.Sockets; using System.Threading; |
2. 서버 프로그램
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | public partial class MainForm : Form { // Thread signal. public static ManualResetEvent allDone = new ManualResetEvent( false ); // Golobal Sockeet define for listener public Socket g_listener = null ; public MainForm() { InitializeComponent(); FormClosing += new FormClosingEventHandler(MainForm_FormClosing); } public void MainForm_FormClosing( object sender, FormClosingEventArgs e) { if (g_listener != null ) { g_listener.Close(); g_listener.Dispose(); } Application.Exit(); } private void btnListen_Click( object sender, EventArgs e) { // button disabled. btnListen.Enabled = false ; // Data buffer for incoming data byte [] bytes = new byte [10240]; // Establish the local endpoint for the socket // The ip address of the computer // running the listener is "192.168.0.12" 예제로... IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(LocalIPAddress()), 11000); // Create a TCP/IP socket g_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections. try { g_listener.Bind(localEndPoint); g_listener.Listen(100); new Thread( delegate () { while ( true ) { // Set the event to nonsignaled state allDone.Reset(); // Start an asynchronous socket to listen for connections. Invoke((MethodInvoker) delegate { listBox1.Items.Add( "Waiting for a connection..." ); }); g_listener.BeginAccept( new AsyncCallback(AcceptCallback), g_listener); // Waiting until a connection is made before continuing. allDone.WaitOne(); } }).Start(); } catch (SocketException se) { MessageBox.Show( string .Format( "StartListening [SocketException] Error : {0} " , se.Message.ToString())); } catch (Exception ex) { MessageBox.Show( string .Format( "StartListening [Exception] Error : {0} " , ex.Message.ToString())); } } public void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue allDone.Set(); // Get the socket that handles the client request. Socket listener = ar.AsyncState as Socket; Socket handler = listener.EndAccept(ar); // Create the state object StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state); } public void ReadCallback(IAsyncResult ar) { string content = string .Empty; // Retrieve the state object and the handler socjet // from the asynchronous state object StateObject state = ar.AsyncState as StateObject; Socket handler = state.workSocket; // Read data from the client socket int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead)); // Check for end-of-flag tag. If it is no there, // Read more data content = state.sb.ToString(); if (content.IndexOf( "<EOF>" ) > -1) { // All the data has been read from the // client. Display it on the console. Invoke((MethodInvoker) delegate { content = TruncateLeft(content, content.Length - 5); listBox1.Items.Add( string .Format( "Read {0} bytes from socket. Data : {1}" , content.Length , content)); }); // Echo the data back to the client Send(handler, content); } else { // Not all data received. Get more handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state); } } } public void Send(Socket handler, string data) { // Convert the string data byte data using UTF8 encoding. byte [] byteData = Encoding.UTF8.GetBytes(data); // Begin sending the data to the remote device. handler.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), handler); } public void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object Socket handler = ar.AsyncState as Socket; // Complete sending the data to remote device int bytesSent = handler.EndSend(ar); Invoke((MethodInvoker) delegate { listBox1.Items.Add( string .Format( "Sent {0} bytes to client" , bytesSent)); listBox1.Items.Add( "" ); }); handler.Shutdown(SocketShutdown.Both); handler.Close(); } catch (SocketException se) { MessageBox.Show( string .Format( "SendCallback [SocketException] Error : {0} " , se.Message.ToString())); } catch (Exception ex) { MessageBox.Show( string .Format( "SendCallback [Exception] Error : {0} " , ex.Message.ToString())); } } public string TruncateLeft( string value, int maxLength) { if ( string .IsNullOrEmpty(value)) return value; return value.Length <= maxLength ? value : value.Substring(0, maxLength); } // Get local IP public 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" ; } private void btnDataClear_Click( object sender, EventArgs e) { listBox1.Items.Clear(); } } // State object for reading client data asynchronously public class StateObject { // Client socket public Socket workSocket = null ; // Size of receive buffer public const int BufferSize = 1024; // Receive buffer public byte [] buffer = new byte [BufferSize]; // Received data string public StringBuilder sb = new StringBuilder(); } |
3. 클라이언트 프로그램
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | private Client client; public MainForm() { InitializeComponent(); FormClosing += new FormClosingEventHandler(MainForm_FormClosing); } private void client_OnDisconnect(Client sender) { UpdateUIListBoxInfo( "Disconnected" ); } private void client_OnReceive( string receiveData) { string content = string .Format( "receiveData : {0}" , receiveData); UpdateUIListBoxInfo(content); UpdateUIListBoxInfo( "" ); } private void client_OnSend(Client sender, int bytesSent) { string content = string .Format( "Sent {0} bytes to server." , bytesSent); UpdateUIListBoxInfo(content); } private void client_OnConnect(Client sender, bool connected) { if (connected) { UpdateUIListBoxInfo( "Connection Accepted....." ); } } public void MainForm_FormClosing( object sender, FormClosingEventArgs e) { if (client.Connected) client.Close(); Application.Exit(); } private void btnSend_Click( object sender, EventArgs e) { client = new Client(txtServerIP.Text); client.OnConnect += new Client.OnConnectEventHandler(client_OnConnect); client.OnSend += new Client.OnSendEventHandler(client_OnSend); client.OnReceive += new Client.OnReceiveEventHandler(client_OnReceive); client.OnDisconnect += new Client.OnDisconnectEventHandler(client_OnDisconnect); string sendData = txtContent.Text; client.StartClient(sendData); } private void UpdateUIListBoxInfo( string content) { if (listBox1.InvokeRequired) { listBox1.BeginInvoke( new MethodInvoker( delegate { listBox1.Items.Add(content); })); } else listBox1.Items.Add(content); } |
'C# with TCP/IP' 카테고리의 다른 글
[Program C#]Socket 통신 - Receiving Data/Handling Disconnection (0) | 2015.01.06 |
---|---|
[Program C#]Socket 통신 - Multiple Connection/Accepting Connections (0) | 2015.01.03 |
[Program C#]비동기 서버/클라이언트 msdn 예제 - 콘솔 버전 (0) | 2014.12.26 |
[Program C#]동기 서버/클라이언트 msdn 예제 - 윈도우 버전 (0) | 2014.12.23 |
[Program C#]동기 서버/클라이언트 msdn 예제 - 콘솔 버전 (0) | 2014.12.23 |