프로그램 설명
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. 소켓/쓰레드과 관련한 네임스페이스를 서버/클라이언트 모두에 포함 시킵니다.
using System.Net; using System.Net.Sockets; using System.Threading;
2. 서버 프로그램
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. 클라이언트 프로그램
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 |