블로그 이미지
따시쿵

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

Notice

2015. 5. 30. 14:22 C# with TCP/IP
프로그램 설명

서버-클라이언트로 구성 된 파일 전송 예제입니다.
한 번에 전송되는 양은 8k 이며, 양방향 통신을 합니다.

1. 기본 클래스와 UI 파일입니다.

기본 클래스 : SocketAcceptedEventArgs, Listener, PacketWriter, PacketReader

Listener.cs PacketIO.cs


UI 파일 : main.cs (서버와 클라이언트가 공통된 UI 를 사용함)


2. QueueType, TransferQueue class 를 정의합니다.

enum QueueType define : 다운로드인지, 업로드인지 구분하는 enum
    public enum QueueType : byte
    {
        Download,
        Upload
    }

class TransferQueue define : 전송되는 queue 에 저장하는 class
    public class TransferQueue
    {
        public static TransferQueue CreateUploadQueue(TransferClient client, string fileName)
        {
            try
            {
                var queue = new TransferQueue();
                queue.Filename = Path.GetFileName(fileName);
                queue.Client = client;
                queue.Type = QueueType.Upload;
                queue.FS = new FileStream(fileName, FileMode.Open);
                queue.Thread = new Thread(new ParameterizedThreadStart(transferProc));
                queue.Thread.IsBackground = true;
                queue.ID = Program.Rand.Next();
                queue.Length = queue.FS.Length;

                return queue;
            }
            catch
            {
                return null;
            }
        }

        public static TransferQueue CreateDownloadQueue(TransferClient client, int id, string saveName, long length)
        {
            try
            {
                var queue = new TransferQueue();
                queue.Filename = Path.GetFileName(saveName);
                queue.Client = client;
                queue.Type = QueueType.Download;
                queue.FS = new FileStream(saveName, FileMode.Create);
                queue.FS.SetLength(length);
                queue.Length = length;
                queue.ID = id;

                return queue;
            }
            catch
            {
                return null;
            }
        }

        private const int FILE_BUFFER_SIZE = 8175;
        private static byte[] file_buffer = new byte[FILE_BUFFER_SIZE];

        private ManualResetEvent pauseEvent;

        public int ID;
        public int Progress, LastProgress;

        public long Transferred;
        public long Index;
        public long Length;

        public bool Running;
        public bool Paused;

        public string Filename;

        public QueueType Type;

        public TransferClient Client;
        public Thread Thread;
        public FileStream FS;

        private TransferQueue()
        {
            pauseEvent = new ManualResetEvent(true);
            Running = true;
        }

        public void Start()
        {
            Running = true;
            Thread.Start(this);
        }

        public void Stop()
        {
            Running = false;
        }

        public void Pause()
        {
            if(!Paused)
            {
                pauseEvent.Reset();
            }
            else
            {
                pauseEvent.Set();
            }

            Paused = !Paused;
        }

        public void Close()
        {
            try
            {
                Client.Transfers.Remove(ID);
            }
            catch
            { 
            
            }

            Running = false;
            FS.Close();
            pauseEvent.Dispose();

            Client = null;
        }

        public void Write(byte[] bytes, long index)
        {
            lock(this)
            {
                FS.Position = index;
                FS.Write(bytes, 0, bytes.Length);
                Transferred += bytes.Length;
            }
        }

        private static void transferProc(object o)
        {
            TransferQueue queue = (TransferQueue)o;

            while(queue.Running && queue.Index < queue.Length)
            {
                queue.pauseEvent.WaitOne();

                if (!queue.Running)
                    break;

                lock(file_buffer)
                {
                    queue.FS.Position = queue.Index;

                    int read = queue.FS.Read(file_buffer, 0, file_buffer.Length);

                    PacketWriter pw = new PacketWriter();
                    pw.Write((byte)Headers.Chunk);
                    pw.Write(queue.ID);
                    pw.Write(queue.Index);
                    pw.Write(read);
                    pw.Write(file_buffer, 0, read);

                    queue.Transferred += read;
                    queue.Index += read;

                    queue.Client.Send(pw.GetBytes());

                    queue.Progress = (int)((queue.Transferred * 100) / queue.Length);

                    if(queue.LastProgress < queue.Progress)
                    {
                        queue.LastProgress = queue.Progress;

                        queue.Client.callProgressChanged(queue);
                    }

                    Thread.Sleep(1);
                }
            }
            queue.Close();
        }
    }

3. queue 작동 방법을 정의합니다.
    public enum Headers : byte
    {
        Queue,
        Start,
        Stop,
        pause,
        Chunk
    }

4. TransferClient class 정의 합니다.


transferClient calss define : 클라이언트 전송 class

    public class TransferClient
    {
        private Socket _baseSocket;

        private byte[] _buffer = new byte[8192];

        private ConnectCallback _connectCallback;

        private Dictionary<int, TransferQueue> _transfers = new Dictionary<int, TransferQueue>();

        public Dictionary<int, TransferQueue> Transfers
        {
            get { return _transfers; }
        }

        public bool Closed
        {
            get;
            private set;
        }

        public string OutputFolder
        {
            get;
            set;
        }

        public IPEndPoint EndPoint
        {
            get;
            private set;
        }

        public event TransferEventHandler Queued;
        public event TransferEventHandler ProgressChanged;
        public event TransferEventHandler Stopped;
        public event TransferEventHandler Complete;
        public event EventHandler Disconnected;

        public TransferClient()
        {
            _baseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public TransferClient(Socket sock)
        {
            _baseSocket = sock;
            EndPoint = (IPEndPoint)_baseSocket.RemoteEndPoint;
        }

        public void Connect(string hostName, int port, ConnectCallback callback)
        {
            _connectCallback = callback;
            _baseSocket.BeginConnect(hostName, port, connectionCallback, null);
        }

        private void connectionCallback(IAsyncResult ar)
        {
            string error = null;
            try
            {
                _baseSocket.EndConnect(ar);
                EndPoint = (IPEndPoint)_baseSocket.RemoteEndPoint;
            }
            catch(Exception ex)
            {
                error = ex.Message.ToString();
            }

            _connectCallback(this, error);
        }

        public void Run()
        {
            try
            {
                _baseSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.Peek, receiveCallback, null);
            }
            catch
            {
                Close();
            }
        }

        public void QueueTransfer(string fileName)
        {
            try
            {
                TransferQueue queue = TransferQueue.CreateUploadQueue(this, fileName);
                _transfers.Add(queue.ID, queue);
                PacketWriter pw = new PacketWriter();
                pw.Write((byte)Headers.Queue);
                pw.Write(queue.ID);
                pw.Write(queue.Filename);
                pw.Write(queue.Length);
                Send(pw.GetBytes());

                if(Queued != null)
                {
                    Queued(this, queue);
                }
            }
            catch
            {

            }
        }
        
        public void StartTransfer(TransferQueue queue)
        {
            PacketWriter pw = new PacketWriter();
            pw.Write((byte)Headers.Start);
            pw.Write(queue.ID);
            Send(pw.GetBytes());
        }

        public void StopTransfer(TransferQueue queue)
        {
            if(queue.Type == QueueType.Upload)
            {
                queue.Stop();
            }

            PacketWriter pw = new PacketWriter();
            pw.Write((byte)Headers.Stop);
            pw.Write(queue.ID);
            Send(pw.GetBytes());
            queue.Close();
        }

        public void PauseTransfer(TransferQueue queue)
        {
            if(queue.Type == QueueType.Upload)
            {
                queue.Pause();
                return;
            }

            PacketWriter pw = new PacketWriter();
            pw.Write((byte)Headers.pause);
            pw.Write(queue.ID);
            Send(pw.GetBytes());
        }

        public int GetOverallProgress()
        {
            int overall = 0;

            foreach(KeyValuePair<int, TransferQueue> pair in _transfers)
            {
                overall += pair.Value.Progress;
            }
            System.Diagnostics.Trace.WriteLine(string.Format("1. overall = {0}", overall));
            if (overall > 0)
            {
                overall = (overall * 100) / (_transfers.Count * 100);
            }

            System.Diagnostics.Trace.WriteLine(string.Format("2. overall = {0}", overall));
            if (overall > 100)
                overall = 100;

            return overall;
        }

        public void Send(byte[] data)
        {
            if (Closed)
                return;

            lock(this)
            {
                try
                {
                    _baseSocket.Send(BitConverter.GetBytes(data.Length), 0, 4, SocketFlags.None);
                    _baseSocket.Send(data, 0, data.Length, SocketFlags.None);
                }
                catch
                {
                    Close();
                }
            }
        }

        public void Close()
        {
            Closed = true;
            _baseSocket.Close();
            if (_transfers != null)
            {
                _transfers.Clear();
                _transfers = null;
            }
            _buffer = null;
            OutputFolder = null;

            if (Disconnected != null)
                Disconnected(this, EventArgs.Empty);
        }

        private void process()
        {
            PacketReader pr = new PacketReader(_buffer);

            Headers header = (Headers)pr.ReadByte();

            switch(header)
            {
                case Headers.Queue:
                    {
                        int id = pr.ReadInt32();
                        string fileName = pr.ReadString();
                        long length = pr.ReadInt64();

                        TransferQueue queue = TransferQueue.CreateDownloadQueue(this, id, Path.Combine(OutputFolder, Path.GetFileName(fileName)), length);

                        _transfers.Add(id, queue);

                        if (Queued != null)
                        {
                            Queued(this, queue);
                        }

                    }
                    break;
                case Headers.Start:
                    {
                        int id = pr.ReadInt32();

                        if(_transfers.ContainsKey(id))
                        {
                            _transfers[id].Start();
                        }
                    }
                    break;
                case Headers.Stop:
                    {
                        int id = pr.ReadInt32();

                        if (_transfers.ContainsKey(id))
                        {
                            TransferQueue queue = _transfers[id];

                            queue.Stop();
                            queue.Close();

                            if(Stopped != null)
                            {
                                Stopped(this, queue);
                            }

                            _transfers.Remove(id);
                        }
                    }
                    break;
                case Headers.pause:
                    {
                        int id = pr.ReadInt32();

                        if(_transfers.ContainsKey(id))
                        {
                            _transfers[id].Pause();
                        }
                    }
                    break;
                case Headers.Chunk:
                    {
                        int id = pr.ReadInt32();
                        long index = pr.ReadInt64();
                        int size = pr.ReadInt32();
                        byte[] buffer = pr.ReadBytes(size);

                        TransferQueue queue = _transfers[id];

                        queue.Write(buffer, index);

                        queue.Progress = (int)((queue.Transferred * 100) / queue.Length);

                        if(queue.LastProgress < queue.Progress)
                        {
                            queue.LastProgress = queue.Progress;

                            if(ProgressChanged != null)
                            {
                                ProgressChanged(this, queue);
                            }

                            if(queue.Progress == 100)
                            {
                                queue.Close();

                                if(Complete != null)
                                {
                                    Complete(this, queue);
                                }
                            }
                        }
                    }
                    break;
            }
            pr.Dispose();
        }

        private void receiveCallback(IAsyncResult ar)
        {
            try
            {
                int found = _baseSocket.EndReceive(ar);

                if(found >= 4)
                {
                    _baseSocket.Receive(_buffer, 0, 4, SocketFlags.None);

                    int size = BitConverter.ToInt32(_buffer, 0);

                    int read = _baseSocket.Receive(_buffer, 0, size, SocketFlags.None);

                    while(read < size)
                    {
                        read += _baseSocket.Receive(_buffer, read, size - read, SocketFlags.None);
                    }

                    process();
                }

                Run();
            }
            catch
            {
                Close();
            }
        }

        internal void callProgressChanged(TransferQueue queue)
        {
            if (ProgressChanged != null)
                ProgressChanged(this, queue);
        }
    }

5. UI method 를 정의 합니다.


실행 화면




소스 파일 : 
posted by 따시쿵
2015. 5. 25. 15:13 C# with TCP/IP

프로그램 설명


패킷을 이용한 데이타 전송 예제입니다. 로그인과 회원가입을 예로 들어 설명 합니다.

전송할 데이타를 바로 네트워크 스트림에 쓰지 않고 전송 패킷에 저장을 한 후, 일괄 전송하는 방법입니다.


1. 3개의 프로젝트를 먼저 만듭니다.


  MyLogin_Packet : 클래스 라이브러리 타입, dll class 파일, 패킷 정의용

  MyLoginClient1_WindowsForm : 윈도우즈 폼 타입. 클라이언트 폼. exe 파일

  MyLoginServer1_WindowsForm : 윈도우즈 폼 타입. 서버 폼. exe 파일



2. MyLogin_Packet : 클래스 라이브러리 타입, dll class 파일, 패킷 정의용

   

   기본 패킷 정의

namespace MyLogin_Packet
{
    public enum PacketType :int
    {
        Login = 0,
        Login_RESULT,
        Member_REGISTER,
        Member_REGISTER_RESULT
    }

    [Serializable]
    public class Packet
    {
        public int packet_Type;
        public int packet_Length;
        
        public Packet()
        {
            this.packet_Type = 0;
            this.packet_Length = 0;
        }

        public static byte[] Serialize(Object data)
        {
            try
            {
                MemoryStream ms = new MemoryStream(1024 * 4); // packet size will be maximum 4k
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, data);
                return ms.ToArray();
            }
            catch
            {
                return null;
            }
        }

        public static Object Deserialize(byte[] data)
        {
            try
            {
                MemoryStream ms = new MemoryStream(1024 * 4);
                ms.Write(data, 0, data.Length);

                ms.Position = 0;
                BinaryFormatter bf = new BinaryFormatter();
                Object obj = bf.Deserialize(ms);
                ms.Close();
                return obj;
            }
            catch
            {
                return null;
            }
        }
    }
}

   

   파생된 패킷 정의(로그인, 회원가입)

namespace MyLogin_Packet
{
    [Serializable]
    public class Login : Packet
    {
        public string id_str { get; set; }
        public string pw_str { get; set; }

    }
}

namespace MyLogin_Packet
{
    [Serializable]
    public class MemberRegister : Packet
    {
        public string id_str { get; set; }
        public string pw_str { get; set; }
        public string nickname_str { get; set; }
    }
}

   


3. MyLoginClient1_WindowsForm : 윈도우즈 폼 타입. 클라이언트 폼. exe 파일

   

  로그인 버튼 클릭시 전송할 데이타 Login Packet class 로 Serialize 시킴. 받은 데이타는 LoginResult Packet class 로 Deserialize 시킴.

   

        private void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                byte[] buffer = new byte[1024 * 4];

                // 1. connect to server
                TcpClient client = new TcpClient("192.168.0.11", 7778);
                NetworkStream stream = client.GetStream();

                // 2. send the packet
                Login login = new Login();
                login.packet_Type = (int)PacketType.Login;
                login.id_str = textBox1.Text.Trim();
                login.pw_str = textBox2.Text.Trim();

                Packet.Serialize(login).CopyTo(buffer, 0);

                stream.Write(buffer, 0, buffer.Length);

                // 3. receive the packet
                Array.Clear(buffer, 0, buffer.Length);

                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                LoginResult loginResult = (LoginResult)Packet.Deserialize(buffer);

                if (loginResult.result)
                {
                    MessageBox.Show(loginResult.reason, "클라이언트 확인", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    MessageBox.Show(loginResult.reason, "클라이언트 오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                // 4. close the socket
                stream.Close();
                client.Close();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


4. MyLoginServer1_WindowsForm : 윈도우즈 폼 타입. 서버 폼. exe 파일

  

   stream 으로 데이타를 받은 후, PacketType class 로 deserialize 시킴으로, 받은 패킷이 어떤 기능을 하는 패킷인지 구분하는 로직

  

            Packet packet = (Packet)Packet.Deserialize(buffer);

            if (packet == null)
                return;

            switch ((int)packet.packet_Type)
            {
                case (int)PacketType.Login:
                    {
                              // 로그인 로직 추가
                    }
                    break;
                case (int)PacketType.Member_REGISTER:
                    {
                              // 회원가입 로직 추가
                    }
                    break;
            }

   

   Login packet class 로 deserialize 시킴

  

                        // 받은 패킷을 Login class 로 deserialize 시킴
                        Login login = (Login)Packet.Deserialize(buffer);

                        setLog(string.Format("ID : {0}, PWD : {1}", login.id_str, login.pw_str)); // 화면에 display 시킴

   

   Loginresult packet class 로 serialize 시켜서 클라이언트에게 전송함

  

                        // 전송할 패킷을 LoginResult class 로 serialize 시킴
                        LoginResult loginResult = new LoginResult();
                        loginResult.packet_Type = (int)PacketType.Login_RESULT;
                        if (random.Next(1, 100) % 2 == 0)    // 짝수라면.... 로그인 성공 
                        {
                            loginResult.result = true;
                            loginResult.reason = "정상적으로 로그인이 되었습니다.";
                        }
                        else                                // 홀수라면.... 로그인 실패
                        {
                            loginResult.result = false;
                            loginResult.reason = "아이디와 비밀번호를 확인 하시기 바랍니다.";
                        }

                        Array.Clear(buffer, 0, buffer.Length);
                        Packet.Serialize(loginResult).CopyTo(buffer, 0);
                        stream.Write(buffer, 0, buffer.Length);


실행 화면


소스 파일 :


MyLogin_Packet.zip

MyLoginClient1_WindowsForm.zip  MyLoginServer1_WindowsForm.zip

posted by 따시쿵
2015. 5. 20. 11:50 C# with TCP/IP

프로그램 설명


서버에서 연결되어 있는 클라이언트의 유효성을 체크하는 예제입니다.


1. 윈도우폼의 [도구상자]에서 [Timer] 클래스를 끌어다 폼에 추가 


2. 윈도우폼에 체크 박스를 두어서 체크시 클라이언트 connection 체크를 주기적으로 실행.


   메시지 전송시 헤드만 전송하고 바디 전송은 하지 않습니다. 왜냐하면 유효한지만 

   체크하는 것이므로 연결이 정상적인지, 비정상적인지만 체크하면 됩니다.


   client.SendMessage(BitConverter.GetBytes((int)0));


        #region checkBox1_CheckedChanged
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                //
                timer1.Tick += new EventHandler(TimerEventProcessor);

                // Sets the timer interval to 10 seconds.
                timer1.Interval = 10000;
                timer1.Start();
            }
            else
                timer1.Stop();
        }
        #endregion

        #region TimerEventProcessor
        // This is the method to run when the timer is raised.
        private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
        {
            Trace.WriteLine("Event raise the TimerEventProcessor");

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

                    if (client.sck.Connected)
                        client.SendMessage(BitConverter.GetBytes((int)0));  
                    else
                    {
                        this.client_Disconnected(client);
                        DisconnectedClientList(client.sck);
                    }
                }
            });
        }
        #endregion




실행 후


소스 파일 : 

 MyKeepAliveClient1_WindowsForm.zip MyKeepAliveServer1_WindowsForm.zip


posted by 따시쿵
2015. 4. 2. 14:42 C# with TCP/IP

프로그램 설명


텍스트와 이미지 파일을 전송하는 예제입니다.

규칙은 아래 그림과 같습니다.



실행 후



연결 후



텍스트 전송 후



이미지 파일 전송 후




프로그램 작성 순서


1. 서버 프로그램

전체 소스는 아래에 있으며, 핵심적인 내용의 소스만 갈무리해서 올립니다.

AsyncSocketServer.zip

        public void ReceiveAsync()
        {
            socket.BeginReceive(lenBuffer, 0, lenBuffer.Length, SocketFlags.None, receiveCallBack, null);
        }

        public void receiveCallBack(IAsyncResult ar)
        {
            try
            {
                int rec = socket.EndReceive(ar);

                if (rec == 0)
                {
                    if (Disconnected != null)
                    {
                        Disconnected(this);
                        return;
                    }
                }

                if (rec != 4)
                {
                    throw new Exception();
                }
            }
            catch(SocketException se)
            {
                switch(se.SocketErrorCode)
                {
                    case SocketError.ConnectionAborted:
                    case SocketError.ConnectionReset:
                        if (Disconnected != null)
                        {
                            Disconnected(this);
                            return;
                        }
                        break;
                }
            }
            catch(ObjectDisposedException)
            {
                return;
            }
            catch(NullReferenceException)
            {
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }

            buffer = new ReceiveBuffer(BitConverter.ToInt32(lenBuffer, 0));

            socket.BeginReceive(buffer.Buffer, 0, buffer.Buffer.Length, SocketFlags.None, receivePacketCallBack, null);
        }

        public void receivePacketCallBack(IAsyncResult ar)
        {
            int rec = socket.EndReceive(ar);

            if (rec <= 0)
            {
                return;
            }

            buffer.BufStream.Write(buffer.Buffer, 0, rec);

            buffer.ToReceive -= rec;

            if (buffer.ToReceive > 0)
            {
                Array.Clear(buffer.Buffer, 0, buffer.Buffer.Length);

                socket.BeginReceive(buffer.Buffer, 0, buffer.Buffer.Length, SocketFlags.None, receivePacketCallBack, null);
                return;
            }

            if (DataReceived != null)
            {
                buffer.BufStream.Position = 0;
                DataReceived(this, buffer);
            }

            buffer.Dispose();

            ReceiveAsync();
        }


2. 클라이언트 프로그램

전체 소스는 아래에 있으며, 핵심적인 내용의 소스만 갈무리해서 올립니다.


AsyncSocketClient.zip

        void SendText(string text)
        {
            BinaryWriter bw = new BinaryWriter(new MemoryStream());
            bw.Write((int)Commands.String);
            bw.Write(text);
            byte[] data = ((MemoryStream)bw.BaseStream).ToArray();
            bw.BaseStream.Dispose();
            client.Send(data, 0, data.Length);
            data = null;
        }

        void SendImage(string path)
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            byte[] b = File.ReadAllBytes(path);
            bw.Write((int)Commands.Image);
            bw.Write((int)b.Length);
            bw.Write(b);
            bw.Close();
            b = ms.ToArray();
            ms.Dispose();

            client.Send(b, 0, b.Length);
        }
posted by 따시쿵
2015. 3. 26. 13:45 C# with TCP/IP

프로그램 설명


바이트 배열을 이용한 파일 전송을 구현한 예시입니다.

이미지 파일 전송시 데이타 구조와 일반 텍스트 데이타 구조가 다르므로 아래에 그림으로 표시했습니다.

실행 후




이미지 파일 전송 후



메시지 전송 후




프로그램 작성


1. 데이타 버퍼 클래스 (StateObject.cs)


    class StateObject
    {
        // Client socket
        public Socket workSocket = null;

        public const int BufferSize = 4096;

        // Receive buffer
        public byte[] buffer = new byte[BufferSize];
    }


2. 서버 프로그램


    public partial class MainForm : Form
    {
        bool initialFlag = true;
        string receivedPath = string.Empty;
        enum DataPacketType { TEXT = 1, IMAGE };
        int dataType = 0;
        string textData = string.Empty;

        public MainForm()
        {
            InitializeComponent();

            Thread t_handler = new Thread(StartListening);
            t_handler.IsBackground = true;
            t_handler.Start();
        }

        public static ManualResetEvent allDone = new ManualResetEvent(false);
        private void StartListening()
        {
            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 9050);
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                listener.Bind(localEP);
                listener.Listen(10);

                while(true)
                {
                    allDone.Reset();
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                    allDone.WaitOne();
                }
            }
            catch(SocketException se)
            {
                Trace.WriteLine(string.Format("SocketException :{0}", se.Message));
            }
            catch(Exception ex)
            {
                Trace.WriteLine(string.Format("Exception :{0}", ex.Message));
            }
        }

        private void AcceptCallback(IAsyncResult ar)
        {
            allDone.Set();

            Socket listener = ar.AsyncState as Socket;
            Socket handler = listener.EndAccept(ar);

            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
            initialFlag = true;
        }

        private void ReadCallback(IAsyncResult ar)
        {
            int fileNameLen = 0;
            string content = string.Empty;
            StateObject state = ar.AsyncState as StateObject;
            Socket handler = state.workSocket;
            int bytesRead = handler.EndReceive(ar);
            
            if(bytesRead > 0)
            {                
                if (initialFlag)
                {
                    dataType = BitConverter.ToInt32(state.buffer, 0);
                    if (dataType == (int)DataPacketType.IMAGE)
                    { 
                        fileNameLen = BitConverter.ToInt32(state.buffer, 4);
                        string fileName = Encoding.UTF8.GetString(state.buffer, 8, fileNameLen);

                        string pathUser = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                        string pathDownload = Path.Combine(pathUser, "Downloads");

                        receivedPath = Path.Combine(pathDownload, fileName);

                        if (File.Exists(receivedPath))
                            File.Delete(receivedPath);
                    }
                    else if (dataType == (int)DataPacketType.TEXT)
                    {
                        textData = Encoding.UTF8.GetString(state.buffer, 4, bytesRead - 4);
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                    }
                }

                if (dataType == (int)DataPacketType.IMAGE)
                {
                    BinaryWriter bw = new BinaryWriter(File.Open(receivedPath, FileMode.Append));
                    if (initialFlag)
                        bw.Write(state.buffer, 8 + fileNameLen, bytesRead - (8 + fileNameLen));
                    else
                        bw.Write(state.buffer, 0, bytesRead);

                    initialFlag = false;
                    bw.Close();
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                }
            }
            else
            {
                if (dataType == (int)DataPacketType.IMAGE)
                {
                    pictureBox1.ImageLocation = receivedPath;
                    Invoke((MethodInvoker)delegate
                    {
                        lblMessage.Text = "Data has been received";
                    });
                }
                else if (dataType == (int)DataPacketType.TEXT)
                    Invoke((MethodInvoker)delegate
                    {
                        textBox1.AppendText(textData + Environment.NewLine);
                    });
            }
        }
    }


3. 클라이언트 프로그램


    public partial class MainForm : Form
    {
        string m_splitter = "'\\'";
        string m_fName = string.Empty;
        string[] m_split = null;
        byte[] m_clientData = null;
        enum DataPacketType { TEXT = 1, IMAGE };

        public MainForm()
        {
            InitializeComponent();
            
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            char[] delimeter = m_splitter.ToCharArray();

            openFileDialog1.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
            openFileDialog1.ShowDialog();

            textBox1.Text = openFileDialog1.FileName;
            pictureBox1.ImageLocation = openFileDialog1.FileName;

            m_split = textBox1.Text.Split(delimeter);
            int limit = m_split.Length;

            m_fName = m_split[limit - 1].ToString();

            if (textBox1.Text != null)
                btnSend.Enabled = true;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            Thread t_handler = new Thread(SendData);
            t_handler.IsBackground = true;
            t_handler.Start();
        }

        private void SendData()
        {
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            byte[] fileName = Encoding.UTF8.GetBytes(m_fName);
            byte[] fileData = File.ReadAllBytes(textBox1.Text);
            byte[] fileNameLen = BitConverter.GetBytes(fileName.Length);
            byte[] fileType = BitConverter.GetBytes((int)DataPacketType.IMAGE);
            // IMAGE(4 byte) + 파일이름(4 byte) + 파일이름길이(4 byte) + 데이타 길이
            m_clientData = new byte[fileType.Length + 4 + fileName.Length + fileData.Length];

            fileType.CopyTo(m_clientData, 0);
            fileNameLen.CopyTo(m_clientData, 4);
            fileName.CopyTo(m_clientData, 8);
            fileData.CopyTo(m_clientData, 8 + fileName.Length);
            
            clientSocket.Connect(IPAddress.Parse("192.168.0.11"), 9050);
            clientSocket.Send(m_clientData);
            clientSocket.Close();
        }

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

            byte[] textData = Encoding.UTF8.GetBytes(textBox2.Text);
            byte[] fileType = BitConverter.GetBytes((int)DataPacketType.TEXT);
            // TEXT(4 byte) + 데이타 길이
            m_clientData = new byte[fileType.Length + textData.Length];

            fileType.CopyTo(m_clientData, 0);
            textData.CopyTo(m_clientData, 4);

            clientSocket.Connect(IPAddress.Parse("192.168.0.11"), 9050);
            clientSocket.Send(m_clientData);
            clientSocket.Close();
        }
    }

posted by 따시쿵
2015. 3. 20. 18:00 C# with TCP/IP

프로그램 설명


SslStream 클래스를 이용한 통신 방법으로 구현 되었습니다.


보안이 없는 일반 tcp 서버/클라이언트와 비교해서 다른 점은 데이타를 주고 받기 전에 반드시 SSL 핸드세이크의 단계를 거친다는 점입니다.


아래는 msdn 에서 발취한 내용입니다.

https://msdn.microsoft.com/ko-kr/library/system.net.security.sslstream(v=vs.110).aspx

SSL 핸드셰이크라고도 하는 인증 프로세스가 성공하면 서버와 클라이언트(선택적)의 ID가 설정되고 클라이언트와 서버는 SslStream을 사용하여 메시지를 주고받을 수 있습니다. 정보를 보내거나 받기 전에 클라이언트와 서버에서는 SslStream에 제공되는 보안 서비스 및 수준을 확인하여, 선택한 프로토콜, 알고리즘 및 강도가 무결성 및 기밀성 요구 사항을 충족하는지 확인해야 합니다.


작업을 하기 전에 인증서를 만드는 방법을 알고 개발에 사용할 인증서를 만들어야 합니다.


1.

Makecert.exe (Certificate Creation Tool) 사이트에서 다음의 예제와 같이 도스 창에서 명령어를 실행해서 작성합니다.


makecert -r -pe -n "CN=XYZ Company" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my


makecert 파일은 Windows 8.1 을 기준으로 아래의 경로에 있습니다.


 


2.

Visual Studio 를 이용해서 인증서를 테스트 할 수 있는 환경, 즉 사용할 수 있는 인증서로 만듭니다.








여기에 보여지는 소스는 msdn 사이트에 나오는 소스이며 원본 사이트는 아래와 같습니다.

https://msdn.microsoft.com/ko-kr/library/system.net.security.sslstream(v=vs.110).aspx



실행 후




메시지 전송 후




프로그램 작성 방법


1. 서버 프로그램


using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics;

    public sealed class SslTcpServer
    {
        static X509Certificate serverCertificate = null;

        public static void RunServer(string certificate, string password)
        {
            try
            {
                serverCertificate = new X509Certificate(certificate, password);
                
                TcpListener listener = new TcpListener(IPAddress.Any, 8080);
                listener.Start();

                while(true)
                {
                    Console.WriteLine("Waiting for a client to connect...");
                    Console.WriteLine();

                    TcpClient client = listener.AcceptTcpClient();
                    ProcessClient(client);
                }
            }
            catch(Exception ex)
            {
                Trace.WriteLine(string.Format("Error : {0}", ex.Message));
            }
        }

        static void ProcessClient(TcpClient client)
        {
            SslStream sslStream = new SslStream(client.GetStream(), false);

            try
            {
                sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
                
                // Set timeouts for the read and write to 5 seconds.
                //sslStream.ReadTimeout = 5000;
                //sslStream.WriteTimeout = 5000;

                // Read a message from the client.
                Console.WriteLine("Waiting for client message...");
                string messageData = ReadMessage(sslStream);
                Console.WriteLine("Received : {0}", messageData.Substring(0, messageData.IndexOf("$")));

                // Write a message to the client
                messageData = "[reply] " + messageData;
                byte[] message = Encoding.UTF8.GetBytes(messageData);
                sslStream.Write(message);
                Console.WriteLine("Sending hello message");
                Console.WriteLine();
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                sslStream.Close();
                client.Close();
                return;
            }
            finally
            {
                // The client stream will be closed with the sslStream
                // because we specified this behavior when creating
                // the sslStream.
                sslStream.Close();
                client.Close();
            }
        }

        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the client.
            // The client signals the end of the message using the
            // "$" marker.
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                // Read the client's test message.
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF or an empty message.
                if (messageData.ToString().IndexOf("$") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            SslTcpServer.RunServer("XYZ_Company_ver2.pfx", "agrafood01");

            Console.WriteLine("Press the any key to continue...");
            Console.ReadLine();
        }
    }


2. 클라이언트 프로그램


using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics;
using System.Collections;

    public class SslTcpClient
    {
        private static Hashtable certtificateError = new Hashtable();

        // The following method is invoked by the RemoteCertificateValidationDelegate.
        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            // Do not allow this client to communicate with unauthenticated servers.
            return false;
        }

        public static void RunClient(string machineName, string serverName, string inputMessage)
        {
            // Create a TCP/IP client socket.
            // machineName is the host running the server application.
            TcpClient client = new TcpClient(machineName, 8080);
            Console.WriteLine("Client connected.");
            // Create an SSL stream that will close the client's stream.
            SslStream sslStream = new SslStream(
                client.GetStream(),
                false,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                null
                );
            // The server name must match the name on the server certificate.
            try
            {
                sslStream.AuthenticateAsClient(serverName);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                client.Close();
                return;
            }

            // Encode a test message into a byte array.
            // Signal the end of the message using the "$".
            byte[] messsage = Encoding.UTF8.GetBytes(inputMessage + "$");
            // Send hello message to the server. 
            sslStream.Write(messsage);
            sslStream.Flush();

            // Read message from the server.
            string serverMessage = ReadMessage(sslStream);
            Console.WriteLine("Server says: {0}", serverMessage.Substring(0, serverMessage.IndexOf("$")));


            // Close the client connection.
            client.Close();
            Console.WriteLine("Client closed.");
            Console.WriteLine();
        }

        private static string ReadMessage(SslStream sslStream)
        {
            // Read the message sent by the server.
            // The end of the message is signaled using the "$" marker
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;

            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer,0,bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);

                if (messageData.ToString().IndexOf("$") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {            
            string inputMessage = string.Empty;

            do
            {
                Console.Write("Clients says: ");
                inputMessage = Console.ReadLine();
                SslTcpClient.RunClient("192.168.0.12", "XYZ Company", inputMessage);
            } while (inputMessage.ToLower() != "exit");
            
            Console.WriteLine("Press any key to continue...");
            Console.ReadLine();
        }
    }


posted by 따시쿵
2015. 3. 17. 15:41 C# with TCP/IP

프로그램 설명




실행 후




Connect 버튼 클릭 후




메시지 전송 후




프로그램 작성


1. handleClient.cs (서버에서 사용하는 클래스)


    class handleClient
    {
        TcpClient clientSocket = null;
        public Dictionary<Tcpclient, string> clientList = null;

        public void startClient(TcpClient clientSocket, Dictionary<Tcpclient, string> clientList)
        {
            this.clientSocket = clientSocket;
            this.clientList = clientList;

            Thread t_hanlder = new Thread(doChat);
            t_hanlder.IsBackground = true;
            t_hanlder.Start();
        }

        public delegate void MessageDisplayHandler(string message, string user_name);
        public event MessageDisplayHandler OnReceived;

        public delegate void DisconnectedHandler(TcpClient clientSocket);
        public event DisconnectedHandler OnDisconnected;

        private void doChat()
        {
            NetworkStream stream = null;
            try
            {
                byte[] buffer = new byte[1024];
                string msg = string.Empty;
                int bytes = 0;
                int MessageCount = 0;

                while (true)
                {
                    MessageCount++;
                    stream = clientSocket.GetStream();
                    bytes = stream.Read(buffer, 0, buffer.Length);
                    msg = Encoding.Unicode.GetString(buffer, 0, bytes);
                    msg = msg.Substring(0, msg.IndexOf("$"));

                    if (OnReceived != null)
                        OnReceived(msg, clientList[clientSocket].ToString());
                }
            }
            catch (SocketException se)
            {
                Trace.WriteLine(string.Format("doChat - SocketException : {0}", se.Message));

                if (clientSocket != null)
                {
                    if (OnDisconnected != null)
                        OnDisconnected(clientSocket);

                    clientSocket.Close();
                    stream.Close();
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(string.Format("doChat - Exception : {0}", ex.Message));

                if (clientSocket != null)
                {
                    if (OnDisconnected != null)
                        OnDisconnected(clientSocket);

                    clientSocket.Close();
                    stream.Close();
                }
            }
        }

    }


2. 서버 프로그램


    public partial class MainForm : Form
    {
        TcpListener server = null;
        TcpClient clientSocket = null;
        static int counter = 0;

        public Dictionary<Tcpclient, string> clientList = new Dictionary<Tcpclient,string>();
 
        public MainForm()
        {
            InitializeComponent();

            // socket start
            Thread t = new Thread(InitSocket);
            t.IsBackground = true;
            t.Start();
        }

        private void InitSocket()
        {
            server = new TcpListener(IPAddress.Any, 9999);
            clientSocket = default(TcpClient);
            server.Start();
            DisplayText(">> Server Started");

            while(true)
            {
                try
                {
                    counter++;
                    clientSocket = server.AcceptTcpClient();
                    DisplayText(">> Accept connection from client");

                    NetworkStream stream = clientSocket.GetStream();
                    byte[] buffer = new byte[1024];
                    int bytes = stream.Read(buffer, 0, buffer.Length);
                    string user_name = Encoding.Unicode.GetString(buffer, 0, bytes);
                    user_name = user_name.Substring(0, user_name.IndexOf("$"));

                    clientList.Add(clientSocket, user_name);

                    // send message all user
                    SendMessageAll(user_name + " Joined ", "",  false);

                    handleClient h_client = new handleClient();
                    h_client.OnReceived += new handleClient.MessageDisplayHandler(OnReceived);
                    h_client.OnDisconnected += new handleClient.DisconnectedHandler(h_client_OnDisconnected);                    
                    h_client.startClient(clientSocket, clientList);
                }
                catch (SocketException se)
                {
                    Trace.WriteLine(string.Format("InitSocket - SocketException : {0}", se.Message));
                    break;
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("InitSocket - Exception : {0}", ex.Message));
                    break;
                }
            }

            clientSocket.Close();
            server.Stop();
        }

        void h_client_OnDisconnected(TcpClient clientSocket)
        {
            if (clientList.ContainsKey(clientSocket))
                clientList.Remove(clientSocket);
        }

        private void OnReceived(string message, string user_name)
        {
            string displayMessage = "From client : " + user_name + " : " + message;
            DisplayText(displayMessage);
            SendMessageAll(message, user_name, true);
        }

        public void SendMessageAll(string message, string user_name, bool flag)
        {
            foreach(var pair in clientList)
            {
                Trace.WriteLine(string.Format("tcpclient : {0} user_name : {1}", pair.Key, pair.Value));

                TcpClient client = pair.Key as TcpClient;
                NetworkStream stream = client.GetStream();
                byte[] buffer = null;

                if(flag)
                {
                    buffer = Encoding.Unicode.GetBytes(user_name + " says : " + message);
                }
                else
                {
                    buffer = Encoding.Unicode.GetBytes(message);
                }
                
                stream.Write(buffer, 0, buffer.Length);
                stream.Flush();
            }
        }

        private void DisplayText(string text)
        {
            if (richTextBox1.InvokeRequired)
            {
                richTextBox1.BeginInvoke(new MethodInvoker(delegate
                {
                    richTextBox1.AppendText(text + Environment.NewLine);
                }));
            }
            else
                richTextBox1.AppendText(text + Environment.NewLine);
        }
    }


3. 클라이언트 프로그램


    public partial class MainForm : Form
    {
        TcpClient clientSocket = new TcpClient();
        NetworkStream stream = default(NetworkStream);
        string message = string.Empty;

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnSendText_Click(object sender, EventArgs e)
        {
            byte[] buffer = Encoding.Unicode.GetBytes(this.textBoxMessage.Text + "$");
            stream.Write(buffer, 0, buffer.Length);
            stream.Flush();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            clientSocket.Connect("192.168.0.12", 9999);
            stream = clientSocket.GetStream();

            message = "Connected to Chat Server";
            DisplayText(message);

            byte[] buffer = Encoding.Unicode.GetBytes(this.textBoxNickName.Text + "$");
            stream.Write(buffer, 0, buffer.Length);
            stream.Flush();

            Thread t_handler = new Thread(GetMessage);
            t_handler.IsBackground = true;
            t_handler.Start();
        }

        private void GetMessage()
        {
            while(true)
            {
                stream = clientSocket.GetStream();
                int BUFFERSIZE = clientSocket.ReceiveBufferSize;
                byte[] buffer = new byte[BUFFERSIZE];
                int bytes = stream.Read(buffer, 0, buffer.Length);

                string message = Encoding.Unicode.GetString(buffer, 0, bytes);
                DisplayText(message);
            }
        }

        private void DisplayText(string text)
        {
            if (richTextBox1.InvokeRequired)
            {
                richTextBox1.BeginInvoke(new MethodInvoker(delegate
                {
                    richTextBox1.AppendText(text + Environment.NewLine);
                }));
            }
            else
                richTextBox1.AppendText(text + Environment.NewLine);
        }
    }


posted by 따시쿵
2015. 3. 14. 17:30 C# with TCP/IP

프로그램 설명


1:1 통신에 이어서 1:N 통신을 다루는 프로그램입니다.

각 클라이언트 소켓마다 쓰레드를 만들어서 통신하는 방법입니다.





실행 후




메신지 전송 후




프로그램 작성 순서


1. 서버 사이드 소켓 핸들 (handleClient.cs)


    class handleClient
    {
        TcpClient clientSocket;
        int clientNo;

        public void startClient(TcpClient ClientSocket, int clientNo)
        {
            this.clientSocket = ClientSocket;
            this.clientNo = clientNo;

            Thread t_hanlder = new Thread(doChat);
            t_hanlder.IsBackground = true;
            t_hanlder.Start();
        }

        public delegate void MessageDisplayHandler(string text);
        public event MessageDisplayHandler OnReceived;

        public delegate void CalculateClientCounter();
        public event CalculateClientCounter OnCalculated;

        private void doChat()
        {
            NetworkStream stream = null;
            try
            { 
                byte[] buffer = new byte[1024];
                string msg = string.Empty;
                int bytes = 0;
                int MessageCount = 0;                

                while(true)
                {
                    MessageCount++;
                    stream = clientSocket.GetStream();
                    bytes = stream.Read(buffer, 0, buffer.Length);
                    msg = Encoding.Unicode.GetString(buffer, 0, bytes);
                    msg = msg.Substring(0, msg.IndexOf("$"));
                    msg = "Data Received : " + msg;

                    if (OnReceived != null)
                        OnReceived(msg);

                    msg = "Server to client(" + clientNo.ToString() + ") " + MessageCount.ToString();
                    if (OnReceived != null)
                        OnReceived(msg);

                    byte[] sbuffer = Encoding.Unicode.GetBytes(msg);
                    stream.Write(sbuffer, 0, sbuffer.Length);
                    stream.Flush();

                    msg = " >> " + msg;
                    if (OnReceived != null) { 
                        OnReceived(msg);
                        OnReceived("");
                    }
                }
            }
            catch(SocketException se)
            {
                Trace.WriteLine(string.Format("doChat - SocketException : {0}", se.Message));

                if (clientSocket != null)
                {
                    clientSocket.Close();
                    stream.Close();
                }

                if (OnCalculated != null)
                    OnCalculated();
            }
            catch (Exception ex)
            {
                Trace.WriteLine(string.Format("doChat - Exception : {0}", ex.Message));

                if (clientSocket != null)
                {
                    clientSocket.Close();
                    stream.Close();
                }

                if (OnCalculated != null)
                    OnCalculated();
            }
        }
    }


2. 서버 프로그램


    public partial class MainForm : Form
    {
        TcpListener server = null;
        TcpClient client = null;
        static int counter = 0;

        public MainForm()
        {
            InitializeComponent();

            // socket start
            Thread t = new Thread(InitSocket);
            t.IsBackground = true;
            t.Start();
        }
        
        private void InitSocket()
        {
            server = new TcpListener(IPAddress.Any, 9999);
            client = default(TcpClient);
            server.Start();
            DisplayText(">> Server Started");

            while(true)
            {
                try
                { 
                    counter++;
                    client = server.AcceptTcpClient();
                    DisplayText(">> Accept connection from client");

                    handleClient h_client = new handleClient();
                    h_client.OnReceived += new handleClient.MessageDisplayHandler(DisplayText);
                    h_client.OnCalculated += new handleClient.CalculateClientCounter(CalculateCounter);
                    h_client.startClient(client, counter);
                }
                catch (SocketException se)
                {
                    Trace.WriteLine(string.Format("InitSocket - SocketException : {0}", se.Message));
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("InitSocket - Exception : {0}", ex.Message));
                }
            }        
        }

        private void CalculateCounter()
        {
            counter--;
        }

        private void DisplayText(string text)
        {
            if (richTextBox1.InvokeRequired)
            {
                richTextBox1.BeginInvoke(new MethodInvoker(delegate
                {
                    richTextBox1.AppendText(text + Environment.NewLine);
                }));
            }
            else
                richTextBox1.AppendText(text + Environment.NewLine); 
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (client != null)
            {
                client.Close();
                client = null;
            }

            if (server != null)
            {
                server.Stop();
                server = null;
            }
        }
    }


3. 클라이언트 프로그램


    public partial class MainForm : Form
    {
        TcpClient clientSocket = new TcpClient();

        public MainForm()
        {
            InitializeComponent();

            new Thread(delegate()
                {
                    InitSocket();
                }).Start();            
        }

        private void InitSocket()
        {
            try
            {
                clientSocket.Connect("192.168.0.12", 9999);
                DisplayText("Client Started");
                labelStatus.Text = "Client Socket Program - Server Connected ...";
            }
            catch (SocketException se)
            {
                MessageBox.Show(se.Message, "Error");                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            NetworkStream stream = clientSocket.GetStream();
            byte[] sbuffer = Encoding.Unicode.GetBytes(richTextBox2.Text + "$");
            stream.Write(sbuffer, 0, sbuffer.Length);
            stream.Flush();

            byte[] rbuffer = new byte[1024];
            stream.Read(rbuffer, 0, rbuffer.Length);
            string msg = Encoding.Unicode.GetString(rbuffer);
            msg = "Data from Server : " + msg;
            DisplayText(msg);

            richTextBox2.Text = "";
            richTextBox2.Focus();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (clientSocket != null)
                clientSocket.Close();
        }

        private void DisplayText(string text)
        {
            if (richTextBox1.InvokeRequired)
            {
                richTextBox1.BeginInvoke(new MethodInvoker(delegate
                {
                    richTextBox1.AppendText(Environment.NewLine + " >> " + text);
                }));
            }
            else
                richTextBox1.AppendText(Environment.NewLine + " >> " + text);
        }
    }


posted by 따시쿵
2015. 3. 12. 16:41 C# with TCP/IP

프로그램 설명


한 프로그램에서 여러개의 포트를 열어서 작업이 필요한 경우입니다.

포트별로 쓰레드를 만들어서 작업하는 방식입니다. 예제에서는 8080, 8081 포트를 엽니다.




실행 후



프로그램 작성 순서


1. ListenPorts.cs


    class ListenPorts
    {
        Socket[] socket;
        IPEndPoint[] ipEndPoint;

        internal ListenPorts(IPEndPoint[] ipEndPoint)
        {
            this.ipEndPoint = ipEndPoint;
            socket = new Socket[ipEndPoint.Length];
        }

        public void beginListen()
        {
            for(int i = 0; i < ipEndPoint.Length; i++)
            {
                socket[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket[i].Bind(ipEndPoint[i]);

                Thread t_handler = new Thread(threadListen);
                t_handler.IsBackground = true;
                t_handler.Start(socket[i]);
            }
        }

        private void threadListen(object sender)
        {
            Socket m_client = sender as Socket;
            byte[] data = new byte[1024];
            
            try
            {
                m_client.Listen(100);
                Socket newSocket = m_client.Accept();
                int bytes = newSocket.Receive(data);

                IPEndPoint remoteIP = newSocket.RemoteEndPoint as IPEndPoint;
                IPEndPoint localIP = newSocket.LocalEndPoint as IPEndPoint;

                Console.WriteLine("server ip : {0} remote ip : {1} ", localIP.ToString(), remoteIP.ToString());
                Console.WriteLine("Received data : {0}", Encoding.Unicode.GetString(data, 0, bytes));
                
                string msg = "Welcome to multiple server";
                byte[] buffer = Encoding.Unicode.GetBytes(msg);
                newSocket.Send(buffer, buffer.Length, SocketFlags.None);
                Console.WriteLine("Send data : {0}", msg);
                Console.WriteLine();
            }
            catch(SocketException se)
            {
                Console.WriteLine(se.Message);
            }
            
        }
    }


2. 서버 프로그램


    class Program
    {
        static void Main(string[] args)
        {
            IPEndPoint ipEndPoint1 = new IPEndPoint(IPAddress.Any, 8080);
            IPEndPoint ipEndPoint2 = new IPEndPoint(IPAddress.Any, 8081);

            IPEndPoint[] ipEndPoint = new IPEndPoint[2] { ipEndPoint1, ipEndPoint2 };
            //IPEndPoint[] ipEndPoint = new IPEndPoint[1] { ipEndPoint1 };

            ListenPorts listenport = new ListenPorts(ipEndPoint);
            listenport.beginListen();
            Console.WriteLine("Begin Listen");
            Console.WriteLine();
            
            Console.ReadKey();
        }
    }


3. 클라이언트 프로그램


    class Program
    {
        static void Main(string[] args)
        {
            byte[] data = new byte[1024];

            //TCP Client

            Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());
            Console.WriteLine();

            //Set the IP address of the server, and its port.
            IPEndPoint ipep1 = new IPEndPoint(IPAddress.Parse("192.168.0.12"), 8080);
            IPEndPoint ipep2 = new IPEndPoint(IPAddress.Parse("192.168.0.12"), 8081);
            string welcome = "Hello, Multiple server ! ";

            // port 8080 으로 전송
            try
            {
                // 소켓 생성
                Socket server1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // 메시지 전송
                data = Encoding.Unicode.GetBytes(welcome);
                server1.Connect(ipep1);
                server1.Send(data);
                Console.WriteLine("Send by the port : {0}", server1.LocalEndPoint.ToString());
                Console.WriteLine("Send data : {0}", welcome);

                // 메시지 받음
                byte[] msg = new byte[1024];
                int bytes = server1.Receive(msg);
                Console.WriteLine("Received data : {0}", Encoding.Unicode.GetString(msg, 0, bytes));
                Console.WriteLine();
                // 소켓 닫기
                server1.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            // port 8081 으로 전송
            try
            {
                // 소켓 생성
                Socket server2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // 메시지 전송
                data = Encoding.Unicode.GetBytes(welcome);
                server2.Connect(ipep2);
                server2.Send(data);
                Console.WriteLine("Send by the port : {0}", server2.LocalEndPoint.ToString());
                Console.WriteLine("Send data : {0}", welcome);

                // 메시지 받음
                byte[] msg = new byte[1024];
                int bytes = server2.Receive(msg);
                Console.WriteLine("Received data : {0}", Encoding.Unicode.GetString(msg, 0, bytes));
                Console.WriteLine();
                // 소켓 닫기
                server2.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadKey();
        }
    }


posted by 따시쿵
2015. 3. 12. 10:20 C# with TCP/IP

프로그램 설명


TcpListener와 TcpClient를 이용한 1:1 통신을 하는 프로그램입니다.

서버와 클라이언트 통신하는 순서와 아래와 같습니다.




실행 후




메시진 전송 후




프로그램 작성 순서


1. 서버 프로그램


    public partial class MainForm : Form
    {
        TcpListener serverSocket = null;
        TcpClient clientSocket = null;

        public MainForm()
        {
            InitializeComponent();

            // socket start
            new Thread(delegate()
                {
                    InitSocket();
                }).Start();
        }

        private void InitSocket()
        {
            try
            { 
                serverSocket = new TcpListener(IPAddress.Any, 9999);
                clientSocket = default(TcpClient);
                serverSocket.Start();
                DisplayText(" >> Server Started");

                clientSocket = serverSocket.AcceptTcpClient();
                DisplayText(" >> Accept connection from client");

                Thread threadHandler = new Thread(new ParameterizedThreadStart(OnAccepted));
                threadHandler.IsBackground = true;
                threadHandler.Start(clientSocket);
            }
            catch (SocketException se)
            {
                DisplayText(string.Format("InitSocket : SocketException : {0}", se.Message));
            }
            catch (Exception ex)
            {
                DisplayText(string.Format("InitSocket : Exception : {0}", ex.Message));
            }
        }

        private void OnAccepted(object sender)
        {
            TcpClient clientSocket = sender as TcpClient;

            while (true)
            {
                try
                {
                    NetworkStream stream = clientSocket.GetStream();
                    byte[] buffer = new byte[1024];

                    stream.Read(buffer, 0, buffer.Length);
                    string msg = Encoding.Unicode.GetString(buffer);
                    msg = msg.Substring(0, msg.IndexOf("$"));
                    DisplayText(" >> Data from client - " + msg);

                    string response = "Last Message from client - " + msg;
                    byte[] sbuffer = Encoding.Unicode.GetBytes(response);

                    stream.Write(sbuffer, 0, sbuffer.Length);
                    stream.Flush();

                    DisplayText(" >> " + response);
                }
                catch (SocketException se)
                {
                    DisplayText(string.Format("OnAccepted : SocketException : {0}", se.Message));
                    break;
                }
                catch (Exception ex)
                {
                    DisplayText(string.Format("OnAccepted : Exception : {0}", ex.Message));
                    break;
                }
            }

            clientSocket.Close();
        }

        private void DisplayText(string text)
        {
            if (richTextBoxMsg.InvokeRequired)
            {
                richTextBoxMsg.BeginInvoke(new MethodInvoker(delegate
                {
                    richTextBoxMsg.AppendText(text + Environment.NewLine);
                }));
            }
            else
                richTextBoxMsg.AppendText(text + Environment.NewLine);
 
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (clientSocket != null)
            { 
                clientSocket.Close();
                clientSocket = null;
            }

            if (serverSocket != null)
            {
                serverSocket.Stop();
                serverSocket = null;
            }
        }
    }


2. 클라이언트 프로그램


    public partial class MainForm : Form
    {
        TcpClient clientSocket = new TcpClient();

        public MainForm()
        {
            InitializeComponent();

            new Thread(delegate()
            {
                InitSocket();
            }).Start();      
        }

        private void InitSocket()
        {
            try
            { 
                clientSocket.Connect("192.168.0.12", 9999);
                DisplayText("Client Started");
                labelStatus.Text = "Client Socket Program - Server Connected ...";
            }
            catch (SocketException se) 
            {
                MessageBox.Show(se.Message, "Error");
            }
            catch (Exception ex) 
            {
                MessageBox.Show(ex.Message, "Error");
            }
        }
        
        private void btnSend_Click(object sender, EventArgs e)
        {
            NetworkStream stream = clientSocket.GetStream();
            byte[] sbuffer = Encoding.Unicode.GetBytes(richTextBox2.Text + "$");
            stream.Write(sbuffer, 0, sbuffer.Length);
            stream.Flush();

            byte[] rbuffer = new byte[1024];
            stream.Read(rbuffer, 0, rbuffer.Length);
            string msg = Encoding.Unicode.GetString(rbuffer);
            DisplayText(msg);

            richTextBox2.Text = "";
            richTextBox2.Focus();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (clientSocket != null)
                clientSocket.Close();
        }

        private void DisplayText(string text)
        {
            if (richTextBox1.InvokeRequired)
            {
                richTextBox1.BeginInvoke(new MethodInvoker(delegate
                {
                    richTextBox1.AppendText(Environment.NewLine + " >> " + text);
                }));
            }
            else
                richTextBox1.AppendText(Environment.NewLine + " >> " + text);
        }
    }


posted by 따시쿵