블로그 이미지
따시쿵

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. 3. 2. 17:16 C#

프로그램 설명


BackgroundWorker 클래스를 이용한 프로그램을 만들어 봤습니다.


두 가지 방법으로 만들었는데,

첫번째 방법은 도구 상자에서 Background 컴포넌트를 디자인 화면에 드래그하는 방법과 두번째는 스크립트로 직접 타이핑을 하는 방법으로 개발했습니다.


첫번째 프로그램에 thread id 를 Debug 시에 출력을 해서 어떤 method 가 ui thread와 다르게 운영되는지 확인 해 보았습니다. 예상한대로 DoWork method 가 ui thread와 다르네요.


new Thread와 비교를 해보면 화면 출력을 편리하게 할 수 있고, 진행 상황을 확인해야 하는 프로그램에 적용하면 편리하게 사용이 가능할 듯 합니다.

 

실행 후





프로그램 작성


1. 첫번째 프로그램


        public MainForm()
        {
            InitializeComponent();

            Debug.WriteLine("MainForm() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }

        #region start buton click method
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy)
                label2.Text = "Busy processing, please waiting!!!!";
            else
                backgroundWorker1.RunWorkerAsync();

            Debug.WriteLine("btnStart_Click() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion
             
        #region cancel buton click method
        private void btnCalcel_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy)
                backgroundWorker1.CancelAsync();
            else
                label2.Text = "No cancel processing !!!";

            Debug.WriteLine("btnCalcel_Click() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

        #region backgroundworker DoWork event
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            Debug.WriteLine("backgroundWorker1_DoWork() thread id : {0}", Thread.CurrentThread.ManagedThreadId);

            int sum = 0;
            for(int i = 0; i<= 100; i++)
            {
                simulateHeavyWork();
                sum += i;
                backgroundWorker1.ReportProgress(i);

                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    backgroundWorker1.ReportProgress(0);
                    return;
                }
            }

            e.Result = sum;
        }
        #endregion

        #region simulate heavy work
        private void simulateHeavyWork()
        {
            Thread.Sleep(100);
        }
        #endregion

        #region backgroundworker ProgressChanged event
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label1.Text = e.ProgressPercentage.ToString() + " %";

            Debug.WriteLine("ProgressChanged() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

        #region backgroundworker RunWorkerCompleted event
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                label1.Text = "Processing cancelled";
            else if (e.Error != null)
                label1.Text = e.Error.Message;
            else
                label1.Text = "Sum = " + e.Result.ToString();

            Debug.WriteLine("backgroundWorker1_RunWorkerCompleted() thread id : {0}", Thread.CurrentThread.ManagedThreadId);
        }
        #endregion

        #region program close
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

 


2. 두번째 프로그램


        private BackgroundWorker myWorker = null;

        #region MainForm() - BackgroundWorker create
        public MainForm()
        {
            InitializeComponent();
            myWorker = new BackgroundWorker();

            myWorker.WorkerReportsProgress = true;
            myWorker.WorkerSupportsCancellation = true;

            myWorker.DoWork += new DoWorkEventHandler(myWork_DoWork);
            myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
            myWorker.ProgressChanged += new ProgressChangedEventHandler(myWorker_ProgressChanged);
        }
        #endregion

        #region backgroundworker DoWork event
        void myWork_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker sendingWorker = sender as BackgroundWorker;
            object[] arrObjects = e.Argument as object[];

            int maxValue = (int)arrObjects[0];
            StringBuilder sb = new StringBuilder();

            float percentage = 0;
            for (int i = 0; i <= maxValue; i++)
            {
                sb.Append(string.Format("Counting number : {0}{1}", PerformHeavyOperation(i), Environment.NewLine));
                percentage = 100 / (float)maxValue * i;
                sendingWorker.ReportProgress((int)percentage);

                if (sendingWorker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
            }

            e.Result = sb.ToString();
        }
        #endregion

        #region backgroundworker RunWorkerCompleted event
        void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                lblStatus.Text = "User Cancelled";
            }
            else if (e.Error != null)
            {
                txtResult.Text = e.Error.ToString();
                lblStatus.Text = "Error";
            }
            else
            { 
                string result = e.Result.ToString();
                txtResult.Text = result;
                lblStatus.Text = "Done";
            }
        }
        #endregion

        #region backgroundworker ProgressChanged event
        void myWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblStatus.Text = string.Format("Counting number : {0} %...", e.ProgressPercentage.ToString());
        }
        #endregion

        #region simulate heavy work
        private int PerformHeavyOperation(int i)
        {
            System.Threading.Thread.Sleep(100);
            return i * 1000;
        }
        #endregion

        #region start buton click method
        private void btnStart_Click(object sender, EventArgs e)
        {
            int numericValue = (int)this.numericUpDown.Value;
            object[] arrObjects = new object[] { numericValue };

            if (!myWorker.IsBusy)
            {
                if (!string.IsNullOrEmpty(txtResult.Text))
                    txtResult.Text = "";

                myWorker.RunWorkerAsync(arrObjects);
            }
            else
                lblStatus.Text = "Work processing";
        }
        #endregion

        #region clear click method
        private void btnClear_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Clear data?", "Confirm", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK)
                txtResult.Text = "";
        }
        #endregion

        #region cancel buton click method
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (myWorker.IsBusy)
            { 
                myWorker.CancelAsync();
            }
            else
            {
                lblStatus.Text = "No cancel work";
            }
        }
        #endregion

1번 예제 소스 :

BackgroundWorker1.zip

 

2번 예제 소스 :

BackgroundWorker2.zip


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

멀티플(multiple) 윈도우 - 2  (0) 2015.05.07
데이타베이스 라이브러리  (0) 2015.04.22
텍스트 로그 파일 라이브러리 - 3  (0) 2015.02.21
텍스트 로그 파일 라이브러리 - 2  (0) 2015.02.21
멀티플(multiple) 윈도우 - 1  (0) 2015.01.24
posted by 따시쿵
2015. 2. 25. 17:31 C# with UDP/IP

브로드캐스트는 같은 물리적 네트워크 상에 있는 받을 준비가 되어 있는 모든 컴퓨터에게 메시지를 전송하는 기법입니다. 기본적으로 라우터나 게이트웨이는 BROADCAST 메시지를 전달하지 않습니다.


브로드캐스트의 또 다른 제약사항은 인터페이스의 최대 전송 단위(maximum transmission unit, MTU)를 넘지 않는다는 겁니다. 기본적으로 브로드캐스트 패킷은 최대 전송 단위를 초과할 수 없습니다.

예를 들어 1460 (1500 - 20 (IP Header) - 20 (UDP Header)) 과 같습니다.


브로드캐스트 주소는 255.255.255.255 이거나 network broadcast address 입니다.

(예전의 브로드캐스트 주소인 0.0.0.0 은 현재는 네트워크 주소로 사용되고 있습니다.

예를 들어, 당신의 컴퓨터 주소가 192.168.20.0 이고 넷마스크가 255.255.255.0 이라면, 브로드캐스트 주소는 192.168.20.255 입니다. (192.168.20.0 might work for backward compatibility) 


당신의 IP address, netmask를 알고 있다면 다음의 공식을 이용해서 산출할 수 있습니다.

Your Broadcast address is: < IP Address > | ( ˜ Netmask ) 


이론적으로 브로드캐스트에 대한 이해를 돕기 위해서는 아래의 사이트를 참조하시기 바랍니다.

Internetwork Design Guide -- UDP Broadcast Flooding

Broadcasting and Multicasting

UDP 통신 시 브로드캐스트 IP 셋팅하기



브로드캐스트시 IP 셋팅 방법은 아래와 같습니다.


IP 주소의 서브넷 부분을 제외한 호스트 자리를 2진수 1로 채운 것을 말합니다.


1.

제품의 IP주소가 공장 초기 값인 10.1.0.1 이고 서브넷 마스크가 255.0.0.0 이라고 한다면,

네트워크 자리는 10. 까지이며 호스트 주소가 1.0.1 이 부분이 서브넷 마스크가 0.0.0 이기 때문에 

그 부분의 2진수를 1로 다 채우게 되면 10.255.255.255가 되겠습니다.

http://blog.sollae.co.kr/?p=691


2.

제품 IP주소가 192.168.0.100 이고, 서브넷 마스크가 255.255.255.0인 경우는 브로드캐스트 IP가 무엇이 될까요

바로 192.168.0.255입니다. 서브넷 마스크가 나타내는 네트워크 자리는 192.168.0.이며 호스트 자리는 100입니다.

호스트자리를 전체 1로 다 채우면 255가 되겠습니다.

http://blog.sollae.co.kr/?p=691


3.

172 대역을 살펴보겠습니다.

제품 IP주소가 172.16.0.100 이고 서브넷 마스크가 255.255.254.0인 경우의 브로드캐스트 IP는 바로 172.16.1.255입니다.

http://blog.sollae.co.kr/?p=691


4.

ip 주소가 255.255.255.255 를 사용합니다. 같은 물리적 네트워크상의 모든 컴퓨터에게 메시지를 전송합니다.

http://www.tack.ch/multicast/broadcast.shtml



프로그램 설명


sender 가 UdpClient 를 생성하여 broadcast IP 인 255.255.255.255 주소로 메시지를 전송하고, receiver 에서는 메시지 받는 루틴을 만들어서 sender 가 전송한 메시지를 받아서 화면에 보여 줍니다.



실행 후






메시지 전송 후






프로그램 작성 순서


1. sender 프로그램


UDPer class define

    class UDPer
    {
        private const int PORT_NUMBER = 15000;

        public void Send(string message)
        {
            UdpClient client = new UdpClient();
            IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT_NUMBER);
            client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            client.Send(bytes, bytes.Length, ip);
            client.Close();

            if (OnSendMessage != null)
                OnSendMessage(message);
        }

        public delegate void SendMessageHandler(string message);
        public event SendMessageHandler OnSendMessage;
    }


Windows Form define

        UDPer udper = null;
        public SendForm()
        {
            InitializeComponent();

            udper = new UDPer();
            udper.OnSendMessage += new UDPer.SendMessageHandler(udper_OnSendMessage);
        }

        void udper_OnSendMessage(string message)
        {
            Trace.WriteLine(string.Format("sent messge : {0}", message));
            lblResult.Text = message;
        }

        private void button1_Click(object sender, EventArgs e)
        {            
            udper.Send(textBox1.Text);
        }


2. receiver 프로그램


UDPer class define

    class UDPer
    {
        private const int PORT_NUMBER = 15000;

        private UdpClient udp = null;
        IAsyncResult ar_ = null;
        
        public void Start()
        {
            if (udp != null)
            {
                throw new Exception("Alread started, stop first");                
            }

            udp = new UdpClient();

            IPEndPoint localEp = new IPEndPoint(IPAddress.Any, PORT_NUMBER);

            udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            udp.ExclusiveAddressUse = false;
            udp.Client.Bind(localEp);

            StartListening();
        }

        public void Stop()
        {
            try
            {
                if (udp != null)
                {
                    udp.Close();
                    udp = null;
                }
            }
            catch { }
        }

        private void StartListening()
        {
            ar_ = udp.BeginReceive(Receive, new object());
        }

        private void Receive(IAsyncResult ar)
        {
            try
            { 
                if (udp != null)
                { 
                    IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT_NUMBER);
                    byte[] bytes = udp.EndReceive(ar, ref ip);
                    string message = Encoding.UTF8.GetString(bytes);
                    StartListening();

                    if (OnReceiveMessage != null)
                        OnReceiveMessage(message);
                }
            }
            catch(SocketException se)
            {
                Trace.WriteLine(string.Format("SocketException : {0}", se.Message));
            }
            catch(Exception ex)
            {
                Trace.WriteLine(string.Format("Exception : {0}", ex.Message));
            }
        }

        public delegate void ReceiveMessageHandler(string message);
        public event ReceiveMessageHandler OnReceiveMessage;

    }


Windows Form define

        UDPer udper = null;
        bool isBtnCommandEnabled = true;
        public ReceiveForm()
        {
            InitializeComponent();

            udper = new UDPer();
            udper.OnReceiveMessage += new UDPer.ReceiveMessageHandler(udper_OnReceiveMessage);

        }

        protected override void OnClosed(EventArgs e)
        {
            if (udper != null)
                udper.Stop();

            base.OnClosed(e);
        }

        void udper_OnReceiveMessage(string message)
        {
            Trace.WriteLine(string.Format("received message : {0}", message));
            Invoke((MethodInvoker)delegate
            {
                lblReceive.Text = message;
            });
        }

        private void btnCommand_Click(object sender, EventArgs e)
        {
            if (isBtnCommandEnabled)
            { 
                udper.Start();
                UpdateUI(isBtnCommandEnabled);
                isBtnCommandEnabled = false;                
            }
            else
            {
                udper.Stop();                
                UpdateUI(isBtnCommandEnabled);
                isBtnCommandEnabled = true;
            }
        }

        private void UpdateUI(bool isBool)
        {
            if (isBool)
            {
                this.btnCommand.Text = "Stop the UDP Client";
                this.btnCommand.ForeColor = Color.White;
                this.btnCommand.BackColor = Color.Orange;
            }
            else
            {
                this.btnCommand.Text = "Stop the UDP Client";
                this.btnCommand.ForeColor = SystemColors.ControlText;
                this.btnCommand.BackColor = SystemColors.Control;
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            if (udper != null)
                udper.Stop();

            this.Close();
        }


posted by 따시쿵
2015. 2. 25. 15:11 C# with TCP/IP
프로그램 설명


codeproject 의 소켓 라이브러리를 이용한 예제를 만들었습니다.


라이브러리에 대한 자세한 설명은 http://www.codeproject.com/Articles/563627/A-full-library-for-a-Socket-Client-Server-system 를 참고하시면 되고, 기본 라이브러리에서 몇가지 수정한 부분이 있습니다.



서버의 기능 


1. 접속자 리스트 관리 - 각 개인별로 메시지를 전송할 수 있음 

   ==> 사용자 이름에 마우스 오른쪽 버튼을 클릭하면 [메시지 전송하기] contextmenu 가 있으며, 

         이것을 이용해서 개별적으로 메시지를 전송할 수 있음


2. [모두에게] 기능을 추가 해서 전체 참석자에게 일괄적으로 메시지를 전송할 수 있음.


3. log4net 라이브러리를 이용해서 폴더에 날짜별로 로그를 쌓을 수 있음


3. log 탭과 message 탭을 따로 두어서, 서버의 작동 상태나 클라이언트의 연결/비연결 상태는 log 탭에

  실시간으로 보여주고, 클라이언트와의 메시지 확인은 message 탭에서 확인이 가능함



클라이언트 기능


1. [Launch clients...] 기능을 두어서 multiple 접속이 가능하게 구현해 두었으며, 서버의 상태를 확인

   가능함


2. 일반 메시지와 비밀글 기능을 두었음



실행 후






메시지 전송 후






프로그램 작성


codeproject 에서 다운을 받으면 실제적인 라이브러리 프로젝트는 AsyncClientServerLib, BaseClientServerLib, SocketServerLib 3개 입니다.


나머지는 테스트용도 입니다.


여기에 올린 프로그램은 Custom_ClientSock, Custom_ServerSocket 두 개입니다.

테스트 용도라면 아이피 부분만 각자의 환경에 맞게 수정하시면 됩니다.





SocketServer_V4.zip





posted by 따시쿵