블로그 이미지
따시쿵

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. 10. 18:03 C#

비동기 작업을 나타냅니다.


다음 예제에서는 TaskFactory.StartNew 메서드를 사용하여 작업을 시작하는 방법을 보여 줍니다.


출처 : http://msdn.microsoft.com/ko-kr/library/system.threading.tasks.task(v=vs.110).aspx


실행 화면


예제 프로그램

// Expected results:
// 		Task t1 (alpha) is created unstarted.
//		Task t2 (beta) is created started.
//		Task t1's (alpha) start is held until after t2 (beta) is started.
//		Both tasks t1 (alpha) and t2 (beta) are potentially executed on 
//           threads other than the main thread on multi-core machines.
//		Task t3 (gamma) is executed synchronously on the main thread.

            Action<object> action = (object obj) =>
                {
                    Console.WriteLine("Task={0}, obj={1}, Thread={2}",
                        Task.CurrentId, obj.ToString(), Thread.CurrentThread.ManagedThreadId.ToString());
                };

            // Construct aun unstarted task
            Task t1 = new Task(action, "alpha");

            // Construct a started task
            Task t2 = Task.Factory.StartNew(action, "beta");

            // Block the main thread to demonstrate that t2 is executing
            t2.Wait();

            // Launch t1
            t1.Start();

            Console.WriteLine("t1 has been launched. (Main Thread={0})", Thread.CurrentThread.ManagedThreadId.ToString());

            // Wait for the task to finish
            t1.Wait();

            // Construct an unstarted task
            Task t3 = new Task(action, "gamma");

            // Run it synchronously
            t3.RunSynchronously();

            // Although the task was run synchronously. it is a good practice
            // to wait for it in the event exception were thrown by task.
            t3.Wait();

            // 프로그램 종료 방지
            Console.Read();



Task 를 만들어서 실행하는 방법들을 설명합니다.


실행 화면



예제 프로그램


        static void Main(string[] args)
        {
            // use an Action delegate and named method
            Task task1 = new Task(new Action(printMessage));

            // use an anonymous delegate
            Task task2 = new Task(delegate { printMessage(); });

            // use a lambda expressiion and a named method
            Task task3 = new Task(() => printMessage());

            // use a lambda expression and an anonymous method
            Task task4 = new Task(() => { printMessage(); });
            
            task1.Start();
            task2.Start();
            task3.Start();
            task4.Start();

            Console.WriteLine("Main method complete. Press <enter> to finish");
            Console.WriteLine("Main Thread={0}", Thread.CurrentThread.ManagedThreadId.ToString());
            Console.ReadLine();
        }

        private static void printMessage()
        {
            Console.WriteLine("Task={0}, Thread={1}",
                                    Task.CurrentId, Thread.CurrentThread.ManagedThreadId.ToString());
        }


Task<TResult> 를 보여주는 예제입니다.


실행 화면




예제 프로그램

        static void Main(string[] args)
        {
            Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);
            t.Start();
            t.Wait();

            // Get the result (the Result property internally calls Wait) 
            Console.WriteLine("The sum is: " + t.Result);   // An Int32 value
            Console.ReadLine();
        }

        private static Int32 Sum(Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--)
                checked { sum += n; }
            return sum;
        }

posted by 따시쿵
2015. 1. 9. 10:22 C#

윈도우/콘솔 프로그램 중 로그 파일을 남기고 싶을 경우가 종종 있습니다.


클라이언트 경우에는 서버로 데이타를 전송한 목록을 가지고 있다거나 서버에서는 클라이언트에서 전송 된 데이타를 정상적으로 받았는지 확인 해 볼 필요가 있습니다. 이런 경우 텍스트 파일로 남기는 경우가 필요한데 이런 경우에 사용하면 됩니다.


멀티 쓰레드 환경에서 작동하도록 작성했으며 라이브러리와 사용 예제를 올립니다.


실행파일 폴더를 가져와서 Log 폴더를 작성하고, 일자별로 파일을 생성하며 시간별로 로그를 쌓습니다.



LogFile.cs


LogFile.cs


using System;
using System.Data;
using System.Configuration;
using System.IO;
using System.Diagnostics;

/// 
/// Summary description for LogFile
/// 
public class LogFile
{

    private static string strLogDir = System.IO.Directory.GetCurrentDirectory() + @"\Log\";
	private static string strLogFile = "Log";
    private static readonly object thisLock = new object();

	public LogFile()
	{
	}

	public static void SetLogPath(string strDir)
	{
		strLogDir = strDir;
	}

	public static void SetLogFile(string strFile)
	{
		strLogFile = strFile;
	}

	public static void WriteLog(string strLog)
	{
		WriteLog(strLog, LogCode.Infomation, strLogFile);
	}

	public static void WriteLog(string strLog, string strFileName)
	{

		WriteLog(strLog, LogCode.Infomation, strFileName, strLogDir);
	}

	public static void WriteLog(string strLog, string strFileName, string strPath)
	{
		WriteLog(strLog, LogCode.Infomation, strFileName, strPath);
	}

	public static void WriteLog(string strLog, LogCode logCode)
	{
		WriteLog(strLog, logCode, strLogFile);
	}

	public static void WriteLog(string strLog, LogCode logCode, string strFileName)
	{

		WriteLog(strLog, logCode, strFileName, strLogDir);
	}

	public static void WriteLog(string strLog, LogCode logCode, string strFileName, string strPath)
	{
		string strFullName;

		if (!Directory.Exists(strPath))
		{
			Directory.CreateDirectory(strPath);
		}

		if (strPath.EndsWith(@"\") == false || strPath.EndsWith("/") == false)
		{
			strPath = strPath + @"\";
		}
		strFullName = strPath + strFileName + "_" + DateTime.Now.ToShortDateString() + ".txt";

		string strFullLog = DateTime.Now.ToString("HH:mm:ss") + " (" + logCode.ToString() + ")" + " : " + strLog;

        lock(thisLock)
        { 
		    StreamWriter sw = new StreamWriter(strFullName, true, System.Text.Encoding.UTF8, 4096);
		    sw.WriteLine(strFullLog);
		    sw.Close();
        }
	}

	public enum LogCode
	{
		Infomation = 0,
		Success = 1,
		Error = -1,
		Failure = -2,
		Warning = -10,
		SystemError = -101,
		ApplicationError = -201
	}
}


사용예제


            new Thread(delegate()
                {                    
                    for (int i = 0; i <= 100; i++)
                        LogFile.WriteLog(string.Format("Thread[1] = {0}", i.ToString()));

                }).Start();

            new Thread(delegate()
                {
                    for (int i = 0; i <= 100; i++)
                        LogFile.WriteLog(string.Format("Thread[2] = {0}", i.ToString()));

                }).Start();;


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

텍스트 로그 파일 라이브러리 - 2  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
멀티스레드 환경에서 UI 에 데이타 표시할 경우  (0) 2015.01.15
Task 클래스  (0) 2015.01.10
ManualResetEvent 클래스  (0) 2014.12.24
posted by 따시쿵
2015. 1. 9. 07:51 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. 서버 프로그램


        static void Main(string[] args)
        {
            TcpListener server = null;

            try
            {
                // Set the TcpListener on port 13000
                Int32 port = 14000;
                IPAddress localAddr = IPAddress.Parse("127.0.0.1");

                // TcpListener server = new TcpListener(port);
                server = new TcpListener(localAddr, port);

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

                // Buffer for reading data
                byte[] bytes = new byte[256];
                string data = string.Empty;

                // Enter the listening loop
                while(true)
                {
                    Console.WriteLine("Waiting for a connection...");

                    // Perform a blocking call to accept requests.
                    // You could also user server.AcceptSocket() here
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected!");

                    data = string.Empty;

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

                    int bytesRead = 0;
                    // Loop to receive all the data sent by the client
                    while( (bytesRead=stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        // Translate data bytes to a UTF8.
                        data = Encoding.UTF8.GetString(bytes, 0, bytesRead);
                        Console.WriteLine("Received: {0}", data);

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

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

                        // Send back a response
                        stream.Write(msg, 0, msg.Length);
                        Console.WriteLine("Sent: {0}\n", data);
                    }

                    // Shutdown and end connection
                    client.Close();
                }
            }
            catch(SocketException se)
            {
                Console.WriteLine("SocketException : {0}", se.Message.ToString());
            }
            finally
            {
                // Stop listening for new clients
                server.Stop();
            }

            Console.WriteLine("\nHit enter to continue...");
            Console.Read(); 
        }

3. 클라이언트 프로그램


        static void Main(string[] args)
        {
            string sendData = string.Empty;
            do
            {
                Console.Write("\n전송할 데이타를 입력해 주세요 : ");
                sendData = Console.ReadLine();

                if (!string.IsNullOrEmpty(sendData))
                    Connect("127.0.0.1", sendData);
            } while (sendData != "");
            
            Console.WriteLine("\nPress Enter to continue...");
            Console.Read();
        }

        static void Connect(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);

                // Get a client stream for reading and writing
                // Stream stream = client.GetStream() : System.IO needs..
                NetworkStream stream = client.GetStream();

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

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

                Console.WriteLine("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;

                Int32 bytesRead = stream.Read(data, 0, data.Length);
                responseData = Encoding.UTF8.GetString(data, 0, bytesRead);
                Console.WriteLine("Received: {0}", responseData);

                // Close everything
                stream.Close();
                client.Close();
            }
            catch(ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e.Message.ToString());
            }
            catch(SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e.Message.ToString());
            }
        }



posted by 따시쿵
2015. 1. 6. 15:43 C# with TCP/IP

프로그램 설명


다중 접속과 데이타 전송 및 클라이언트에서 소켓 해제시 서버에서 인지를 하고 접속한 클라이언트 소켓을 해제하는 예제입니다.


구조는 서버에서 listen socket 을 생성하고, 각각의 클라이언트 접속시 client class 를 만들어서 리스트뷰에서 현재 상태의 소켓 상태와 메시지를 보여 주는 구조입니다. 


서버 구현시 사용한 listen class, client class 파일 올립니다.

Client.cs  Listener.cs

클라이언트에서는 소켓을 해제하는 단계를 거칩니다.



실행 후



메시지 전송 후



클라이언트 접속 해제 후



프로그램 설명


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

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


2. 서버 프로그램


        Listener listener;

        public Main()
        {
            InitializeComponent();

            int port = Convert.ToInt32(Properties.Settings.Default.Port);
            listener = new Listener(port);
            listener.SocketAccepted += new Listener.SocketAcceptedHandler(listener_SocketAccepted);
            Load += new EventHandler(Main_Load);
        }

        void Main_Load(object sender, EventArgs e)
        {
            string tcpServerIP = Properties.Settings.Default.ServerIP;
            listener.Start(tcpServerIP);
        }

        void listener_SocketAccepted(System.Net.Sockets.Socket e)
        {
            Client client = new Client(e);
            client.Received += new Client.ClientReceivedHandler(client_Received);
            client.Disconnected += new Client.ClientDisconnectedHandler(client_Disconnected);

            Invoke((MethodInvoker)delegate
            {
                ListViewItem i = new ListViewItem();
                i.Text = client.EndPoint.ToString();
                i.SubItems.Add(client.ID);
                i.SubItems.Add("XX");
                i.SubItems.Add("YY");
                i.Tag = client;
                lstClient.Items.Add(i);
            });
        }

        void client_Disconnected(Client sender)
        {
            Invoke((MethodInvoker)delegate
            {                
                for (int i = 0; i < lstClient.Items.Count; i++)
                {
                    Client client = lstClient.Items[i].Tag as Client;

                    if (client.ID == sender.ID)
                    {
                        lstClient.Items.RemoveAt(i);
                        break;
                    }
                }
            });
        }

        void client_Received(Client sender, byte[] data)
        {
            Invoke((MethodInvoker)delegate
            {
                for (int i = 0; i < lstClient.Items.Count; i++)
                {
                    Client client = lstClient.Items[i].Tag as Client;

                    if (client.ID == sender.ID)
                    {
                        lstClient.Items[i].SubItems[2].Text = Encoding.UTF8.GetString(data);
                        lstClient.Items[i].SubItems[3].Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
                        break;
                    }
                }
            });
        }


3. 클라이언트 프로그램


        Socket sck;
        public Main()
        {
            InitializeComponent();
            sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            string ServerIP = Properties.Settings.Default.ServerIP;
            string Port = Properties.Settings.Default.Port;

            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ServerIP), Convert.ToInt32(Port));
            sck.Connect(remoteEP);
            lblInfo.Text = "Connected";
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            int s = sck.Send(Encoding.UTF8.GetBytes(textBox1.Text));
            if (s > 0)
            {
                lblInfo.Text = string.Format("{0} bytes data sent", s.ToString());
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            lblInfo.Text = "Not Connected....";
            sck.Close();
            sck.Dispose();
            Close();
        }


posted by 따시쿵
2015. 1. 3. 09:34 C# with TCP/IP

프로그램 설명


이번 프로그램에서는 클라이언트가 다중으로 접속하는 것을 다루되도록 하겠습니다.


클라이언트는 서버에 접속을 하고 접속을 끊어 버리는 단순한 작업을 합니다. 서버는 연결이 들어오는 것을 어떻게 저장하고 관리하는지를 보여 줍니다.


서버 프로그램에서 사용하는 Listener class 파일을 첨부 파일과 환경 파일에 아이피와 포트를 저장하고 사용합니다. 두가지 모두 올립니다.


Listener.cs   Settings.cs


실행 후



연결 요청 후


프로그램 작성 순서


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

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


2. 서버 프로그램


        static Listener l;
        static List<socket> sockets;

        static void Main(string[] args)
        {
            System.Diagnostics.Debug.WriteLine("{0} : {1}", Properties.Settings.Default.ServerIP, Properties.Settings.Default.Port);
            string serverIP = Properties.Settings.Default.ServerIP;
            string port = Properties.Settings.Default.Port;

            l = new Listener(Convert.ToInt32(port));
            sockets = new List<socket>();

            l.SocketAccepted += new Listener.SocketAcceptedHandler(l_SocketAccepted);
            l.Start(serverIP);

            Console.ReadLine();
        }

        static void l_SocketAccepted(System.Net.Sockets.Socket e)
        {
            Console.WriteLine("New Connection: {0}\n{1}\n=========================", 
                                e.RemoteEndPoint.ToString(), DateTime.Now.ToString());

            if (e != null)
                sockets.Add(e);

            int index = 1;
            Console.WriteLine("Connected socket list\n=========================");
            foreach(Socket s in sockets)
            {
                Console.WriteLine("{0} : {1} : socket handle {2}", index, s.RemoteEndPoint.ToString(), s.Handle.ToString());
                index++;
            }

            Console.WriteLine("");
        }


3. 클라이언트 프로그램


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

            string serverIP = Properties.Settings.Default.ServerIP;
            string port = Properties.Settings.Default.Port;

            s.Connect(IPAddress.Parse(serverIP), Convert.ToInt32(port));
            s.Close();
            s.Dispose();



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

프로그램 설명


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 는 첨부 파일로 올려 놓습니다.

 

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


posted by 따시쿵
2014. 12. 26. 16:47 C# with TCP/IP

프로그램 설명


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


비동기로 소켓을 실행하기 위해 ManualResetEvent 클래스를 사용해서 thread 간 통신을 하며, StateObject class 를 만들어서 받을 데이타를 정의하는 부분이 추가 되었으며, 비동기 호출 method 들(beginAccept, beginReceive, beginSend)을 호출합니다.  


다른 부분들은 동기 서버/클라이언트의 추가 함수들을 같이 사용했습니다.(문자열 자르기, 로컬 아이피 가져오기)


초기에 실행하면 다른점이 보이는데 이 부분이 실제로 비동기 호출을 담당하는 부분이며 소켓을 통해서 데이타를 주고 받는 부분이 비동기로 구현되어 있습니다.


실행 후



메시지 전송 후



프로그램 작성 순서


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

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


2. 서버 프로그램


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

    class Program
    {
        // Thread signal
        public static ManualResetEvent allDone = new ManualResetEvent(false);

        public static 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 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";
        }

        private static void StartListening()
        {
            // Data buffer for incoming data
            byte[] bytes = new byte[1024];

            // Establish the local endpoint for the socket
            // running the listener is "192.168.0.12" 테스트 아이치
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(LocalIPAddress()), 11000);


            // Create a TCP/IP socket
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the local endpoint and listen for incoming connecions.
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(100);

                while(true)
                {
                    // Set the event to nonsignaled state
                    allDone.Reset();

                    // Start an asynchronous socket to listen for connections.
                    Console.WriteLine("\nWaiting for a connections...");
                    listener.BeginAccept(new AsyncCallback(AcceptCallback) , listener);

                    // Wait until a connection is made before running
                    allDone.WaitOne();

                }
            }
            catch (SocketException se)
            {
                Console.WriteLine("StartListening[SocketException] Error : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("StartListening[Exception] Error : {0} ", ex.Message.ToString());
            }

            Console.WriteLine("\nPress ENTER to continue.....\n");
            Console.ReadLine();
        }

        public static void AcceptCallback(IAsyncResult ar)
        {
            // Signal the main thread to continue.
            allDone.Set();

            // Get the socket that handles the client socket
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            // Create the socket object
            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        }

        public static void ReadCallback(IAsyncResult ar)
        {
            string content = string.Empty;

            // Retrieve the state object and the handler socket
            // from the asynchronous state object
            StateObject state = (StateObject)ar.AsyncState;
            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-file tag. If it it not 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.
                    content = TruncateLeft(content, content.Length - 5);
                    Console.WriteLine("Read {0} bytes from socket \nData : {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, 0 , new AsyncCallback(ReadCallback), state);
                }
            }
        }

        private static void Send(Socket handler, string data)
        {
            // Convert the string data to bytes data using UTF8 encoding
            byte[] byteData = Encoding.UTF8.GetBytes(data);

            // Being sending the data to the remote device
            handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback) , handler);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object
                Socket handler = ar.AsyncState as Socket;

                // Complete sending the data to the remote device
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);

                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
            catch (SocketException se)
            {
                Console.WriteLine("SendCallback[SocketException] Error : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("SendCallback[Exception] Error : {0} ", ex.Message.ToString());
            }
        }

        static void Main(string[] args)
        {
            StartListening();
        }
    }


3. 클라이언트 프로그램

    #region State object define
    // State object for receiving data from reomte device
    public class StateObject
    {
        // Client socket
        public Socket workSocket = null;
        // Size of receive buffer
        public const int BufferSize = 256;
        // Receive buffer
        public byte[] buffer = new byte[BufferSize];
        // Received data string
        public StringBuilder sb = new StringBuilder();
    }
    #endregion

    class Program
    {
        // The port number for the remote device
        private const int port = 11000;

        // ManaulResetEvent instances signal completion
        private static ManualResetEvent connectDone = new ManualResetEvent(false);
        private static ManualResetEvent sendDone = new ManualResetEvent(false);
        private static ManualResetEvent receiveDone = new ManualResetEvent(false);

        // The response from the remote device
        private static String response = String.Empty;

        private static void StartClient()
        {
            // Connect to a remote device
            try
            {
                // Establish the remote endpoint for the socket
                // The name of
                // remote device 아이피 "192.168.0.12" : 테스트 목적
                IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("192.168.0.12"), port);
                
                // Create a TCP/IP socket
                Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // Connect to the remote endpoint
                client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
                connectDone.WaitOne();

                // Send user input data to the remote device
                Console.Write("전송할 메시지를 입력해 주세요 : ");
                string sendData = Console.ReadLine() + "<eof>";
                Send(client, sendData);
                sendDone.WaitOne();

                // Receive the response from the remote device.
                Receive(client);
                receiveDone.WaitOne();

                // Write the response to the console
                Console.WriteLine("Response received : {0}", response);

                // Release the socket
                client.Shutdown(SocketShutdown.Both);
                client.Close();
            }
            catch (SocketException se)
            {
                Console.WriteLine("StartClient SocketException Error : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("StartClient Exception Error : {0} ", ex.Message.ToString());
            }
        }

        private static void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object
                Socket client = (Socket)ar.AsyncState;

                // Complete the connection
                client.EndConnect(ar);

                Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());

                // Signal that the connection has been made
                connectDone.Set();
            }
            catch (SocketException se)
            {
                Console.WriteLine("ConnectCallback SocketException Error : {0} ", se.Message.ToString());
            }
            catch(Exception ex)
            {
                Console.WriteLine("ConnectCallback Exception Error : {0} ", ex.Message.ToString());
            }
        }

        private static void Receive(Socket client)
        {
            try
            {
                // Create the state object
                StateObject state = new StateObject();
                state.workSocket = client;

                // Begin receiving the data from the remote device
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
            }
            catch (SocketException se)
            {
                Console.WriteLine("Receive SocketException Error : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("Receive Exception Error : {0} ", ex.Message.ToString());
            }
        }

        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the state object and the client socket
                // from the asynchronous state object
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;

                // Read data from the remote device
                int bytesRead = client.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));

                    // Get the rest of the data
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    // All the data has arrived; put it in response
                    if (state.sb.Length > 1)
                        response = state.sb.ToString();

                    // Signal that all bytes have been received.
                    receiveDone.Set();
                }

            }
            catch (SocketException se)
            {
                Console.WriteLine("ReceiveCallback SocketException Error : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("ReceiveCallback Exception Error : {0} ", ex.Message.ToString());
            }
        }

        private static void Send(Socket client, string data)
        {
            // Convert the string data to byte data using UTF8 encoding
            byte[] byteData = Encoding.UTF8.GetBytes(data);

            // Being sending the data to the remote device
            client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object
                Socket client = ar.AsyncState as Socket;

                // Complete sending the data to the remote device
                int bytesSent = client.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to server", bytesSent);

                // Signal that all bytes have been sent
                sendDone.Set();
            }
            catch (SocketException se)
            {
                Console.WriteLine("SendCallback SocketException Error : {0} ", se.Message.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine("SendCallback Exception Error : {0} ", ex.Message.ToString());
            }
        }
        static void Main(string[] args)
        {
            StartClient();
            Console.ReadLine();
        }
    }


posted by 따시쿵
2014. 12. 24. 11:42 C#

하나 이상의 대기 중인 스레드에 이벤트가 발생했음을 알립니다. 이 클래스는 상속될 수 없습니다.


ManualResetEvent 를 사용하여 스레드는 신호를 보냄으로써 서로 통신할 수 있습니다. 일반적으로 이 통신은 다른 스레드가 처리되기 위해 먼저 하나의 스레드가 완료해야 하는 작업과 관련이 있습니다.


하나의 스레드에서 다른 스레드의 처리를 위해 먼저 완료되어야 하는 작업을 시작할 때 Reset을 호출하여 ManualResetEvent를 신호 없음 상태로 설정합니다. 이 스레드는 ManualResetEvent를 제어하는 것으로 간주될 수 있습니다. ManualResetEvent 에 대해 WaitOne을 호출하는 스레드는 차단되며 신호를 기다립니다. 제어 스레드는 해당 작업을 끝나면 Set을 호출하여 대기 중인 스레드가 계속될 수 있음을 알립니다. 대기 중인 모든 스레드는 해제됩니다.


출처 : http://msdn.microsoft.com/ko-kr/library/system.threading.manualresetevent(v=vs.110).aspx



실행 화면



예제 프로그램

       // mre is used to block and relrease threads manually. It is 
        // created in unsignaled state.
        private static ManualResetEvent mre = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent\n");

            for (int i = 0; i <= 2; i++)
            {
                Thread t = new Thread(ThreadProc);
                t.Name = "Thread_" + i.ToString();
                t.Start();
            }

            #region 테스트1 - Set()
            Thread.Sleep(500);
            Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()\n" +
                              "\nto release all the threads.\n");
            Console.ReadLine();

            mre.Set();

            #endregion

            #region 테스트2 - Reset()
            Thread.Sleep(500);
            Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +
                              "\ndo not block. Press Enter to show this.\n");
            Console.ReadLine();

            for (int i = 3; i <= 4; i++)
            {
                Thread t = new Thread(ThreadProc);
                t.Name = "Thread_" + i.ToString();
                t.Start();

            }
            Thread.Sleep(500);
            Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block\n" +
                              "\nwhen they call WaitOne\n");
            Console.ReadLine();

            mre.Reset();

            #endregion

            #region 테스트3 - Set()
            //Start a thread that waits on the ManualResetEvent
            Thread t5 = new Thread(ThreadProc);
            t5.Name = "Thread_5";
            t5.Start();

            Thread.Sleep(500);
            Console.WriteLine("\nPress Enter to call Set() and conclude the demo\n");
            Console.ReadLine();

            mre.Set();

            #endregion

            Console.ReadLine();
        }

        private static void ThreadProc()
        {
            string name = Thread.CurrentThread.Name;

            Console.WriteLine(name + " starts and call mre.WaitOne()");

            mre.WaitOne();

            Console.WriteLine(name + " ends");
        }


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

프로그램 설명


msdn 사이트에 있는 콘솔 버전을 윈도우 버전으로 수정했습니다.

원본 소스는 아래와 같습니다.


동기 서버 예제 : http://msdn.microsoft.com/ko-kr/library/6y0e13d3(v=vs.110).aspx

동기 클라이언트 예제 : http://msdn.microsoft.com/ko-kr/library/kb5kfec7(v=vs.110).aspx


수정한 부분은 로컬 아이피를 가져오는 method 추가와 문자열 자르기 method(TruncateLeft), 클라이언트가 서버로 전송하는 메시지를 윈도우(textbox)에서 입력 받아서 서버로 전송하는 부분입니다.


클라이언트에서 서버로 전송하는 문자열의 마지막에 <EOF>을 문자열을 추가해서 전송합니다.


예제에서는 클라이언트 3개를 띄워서 테스트를 해 봤습니다.


실행 후




메시지 전송 후



프로그램 작성 순서


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

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


2. 서버 프로그램

        // Incoming data from the client
        public static string data = null;

        // Socket listen, accept
        private Socket listener = null;
        private Socket handler = null;

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

        public static 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 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";
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            // Data buffer from incoming data
            byte[] bytes = new byte[1024];

            // 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
            {
                listener.Bind(localEndPoint);
                listener.Listen(10);

                new Thread(delegate()
                    {
                        // Start listening for connections.
                        while (true)
                        {
                            Invoke((MethodInvoker)delegate
                            {
                                listBox1.Items.Add("Waiting for connections.....");
                            });

                            // Program is suspended while waiting for an incoming connection.
                            handler = listener.Accept();
                            Invoke((MethodInvoker)delegate
                            {
                                listBox1.Items.Add("클라이언트 연결.....OK");
                            });
                            
                            try
                            {
                                data = null;

                                // An incoming connection needs to be processed.
                                while (true)
                                {
                                    bytes = new byte[1024];
                                    int bytesRec = handler.Receive(bytes);
                                    data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
                                    if (data.IndexOf("<eof>") > -1)
                                        break;
                                }

                                // Truncate the <eof>
                                data = TruncateLeft(data, data.Length - 5);

                                // Show the data on the console
                                Invoke((MethodInvoker)delegate
                                {
                                    listBox1.Items.Add(string.Format("Text received : {0}", data));
                                });

                                // Echo the data back to the client
                                data = "[Server Echo 메시지]" + data;
                                byte[] msg = Encoding.UTF8.GetBytes(data);

                                handler.Send(msg);
                            }
                            catch
                            {
                                MessageBox.Show("서버: DISCONNECTION!");
                                handler.Close();
                                handler.Dispose();
                                break;
                            }
                        }
                     }).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());
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
        }


3. 클라이언트 프로그램

        // Client socket
        private Socket sock = null;

        // Data buffer from incomming data
        byte[] bytes = new byte[1024];

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnSendText_Click(object sender, EventArgs e)
        {
            new Thread(() =>
            {
                try
                {
                    // Create a TCP/IP Socket
                    sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    // Connect to the server
                    sock.Connect(new IPEndPoint(IPAddress.Parse(textBox1.Text), 12000));

                    // Send the data through the socket.
                    byte[] msg = Encoding.UTF8.GetBytes(textBox2.Text + "<eof>");
                    int bytesSent = sock.Send(msg);

                    //bytes = null;
                    int bytesRec = sock.Receive(bytes);

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

                    Invoke((MethodInvoker)delegate
                    {
                        listBox1.Items.Add(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
                    });
                }
                catch (SocketException se)
                {
                    MessageBox.Show("SocketException = " + se.Message.ToString());
                    sock.Close();
                    sock.Dispose();
                }
            }).Start();
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            sock.Shutdown(SocketShutdown.Both);
            sock.Close();
        }


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

프로그램 설명


msdn 사이트에 있는 예제를 조금 수정해서 작성했습니다.

원본 소스는 아래와 같습니다.


동기 서버 예제 : http://msdn.microsoft.com/ko-kr/library/6y0e13d3(v=vs.110).aspx

동기 클라이언트 예제 : http://msdn.microsoft.com/ko-kr/library/kb5kfec7(v=vs.110).aspx


수정한 부분은 로컬 아이피를 가져오는 method 추가와 문자열 자르기 method(TruncateLeft), 클라이언트가 서버로 전송하는 메시지를 콘솔에서 입력 받아서 서버로 전송하는 부분입니다.


클라이언트에서 서버로 전송하는 문자열의 마지막에 <EOF>을 문자열을 추가해서 전송합니다.


데모로 나와 있는 소스는 클라이언트가 메시지를 한 번 전송하고, 에코 메시지를 받는 것이 전부입니다. 계속 메시지를 전송할 수 있는 것이 아닙니다.


예제에서는 클라이언트 3개를 띄워서 테스트를 해 봤습니다.


실행 후




메시지 전송 후




프로그램 작성 순서


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

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


2. 서버 프로그램

        // Incoming data from the client
        public static string data = null;

        public static string TruncateLeft(string value, int maxLength)
        {
            if (string.IsNullOrEmpty(value)) return value;
            return value.Length <= maxLength ? value : value.Substring(0, maxLength);
        }

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

        public static void StartListening()
        {
            Socket listener = null;
            Socket handler = null;

            // Data buffer from incoming data
            byte[] bytes = new byte[1024];

            // 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, 11000);

            // Create a TCP/IP Socket
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the local endpoint and
            // listen for incoming connections.
            try{
                listener.Bind(localEndPoint);
                listener.Listen(10);

                // Start listening for connections.
                while(true)
                {
                    Console.WriteLine("Waiting for connections.....");

                    // Program is suspended while waiting for an incoming connection.
                    handler = listener.Accept();
                    data = null;

                    // An incoming connection needs to be processed.
                    while(true)
                    {
                        bytes = new byte[1024];
                        int bytesRec = handler.Receive(bytes);
                        data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
                        if (data.IndexOf("<eof>") > -1)
                            break;
                    }
                    // Truncate the <EOF>
                    data = TruncateLeft(data, data.Length - 5);

                    // Show the data on the console
                    Console.WriteLine("Text received : {0}", data);

                    // Echo the data back to the client
                    data = "[Server Echo 메시지]" + data;
                    byte[] msg = Encoding.UTF8.GetBytes(data);

                    handler.Send(msg);
                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
            }
            catch (SocketException se)
            {
                Console.WriteLine("Socket 에러 : {0}", se.ToString());
                switch(se.SocketErrorCode)
                {
                    case SocketError.ConnectionAborted:
                    case SocketError.ConnectionReset:
                        handler.Close();
                        break;
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        static void Main(string[] args)
        {
            StartListening();
            Console.ReadLine();
        }


2. 클라이언트 프로그램

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

        private static void StartClient()
        {
            // Data buffer fr incomming data
            byte[] bytes = new byte[1024];

            // Connect to a remote device
            try
            {
                // Establish the remote endpoint for the socket.
                // This example uses port 11000 on the local computer.
                IPAddress remoteIPAddress = IPAddress.Parse(LocalIPAddress());
                IPEndPoint remoteEndPoint = new IPEndPoint(remoteIPAddress, 11000);

                // Create a TCP/IP Socket
                Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // Connect the socket to the remote endpoint Catch any errors.
                try
                {
                    sender.Connect(remoteEndPoint);

                    Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString());

                    // Encoding the data string into a byte array.
                    Console.Write("Client 메시지 :");
                    byte[] msg = Encoding.UTF8.GetBytes(Console.ReadLine());
                    
                    // Send the data through the socket.
                    int bytesSent = sender.Send(msg);

                    // Receive the response from the remote device
                    int bytesRec = sender.Receive(bytes);
                    Console.WriteLine("Echoed test = {0}", Encoding.UTF8.GetString(bytes, 0, bytesRec));

                    // Release the socket.
                    sender.Shutdown(SocketShutdown.Both);
                    sender.Close();
                }
                catch(ArgumentNullException ane)
                {
                    Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
                }
                catch(SocketException se)
                {
                    Console.WriteLine("SocketException : {0}", se.ToString());
                }
                catch(Exception e)
                {
                    Console.WriteLine("Unexpected exception : {0}", e.ToString());
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        static void Main(string[] args)
        {
            StartClient();
            Console.ReadLine();
        }


posted by 따시쿵