첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ TcpListener 클래스 : TCP 서버 만들기

------------------------------------------------------------------------------------------------------------------------

 

 


TestSolution.zip


[TestServer 프로젝트]

 

MainForm.cs

 

 

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Security.Cryptography;

using System.Text;

using System.Threading;

using System.Windows.Forms;

 

namespace TestServer

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// TCP 리스너

        /// </summary>

        private TcpListener tcpListener;

 

        /// <summary>

        /// TCP 클라이언트

        /// </summary>

        private TcpClient tcpClient;

 

        /// <summary>

        /// 네트워크 스트림

        /// </summary>

        private NetworkStream networkStream;

 

        /// <summary>

        /// 스트림 라이터

        /// </summary>

        private StreamWriter streamWriter;

 

        /// <summary>

        /// 서버 작업 여부

        /// </summary>

        private bool isServerWorking = false;

 

        /// <summary>

        /// 스레드

        /// </summary>

        private Thread thread;

 

        /// <summary>

        /// 트리플 DES 암호 서비스 공급자

        /// </summary>

        private TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();

 

        /// <summary>

        /// 개인 키 바이트 배열

        /// </summary>

        private byte[] privateKeyByteArray = new byte[]

        {

            98 , 45 , 125, 56, 1 , 60 , 11, 38 ,

            123, 54 , 234, 9 , 76, 20 , 44, 7  ,

            12 , 223, 219, 95, 48, 156, 32, 239

        };

 

        /// <summary>

        /// 개인 키 초기 값 바이트 배열

        /// </summary>

        private byte[] privateKeyInitialValueByteArray = new byte[]

        {

            67, 12, 3, 41, 66, 78, 34, 123

        };

 

        /// <summary>

        /// 난수기

        /// </summary>

        Random random = new Random();

 

        /// <summary>

        /// 임의 값

        /// </summary>

        private int randomValue = 0;

 

        /// <summary>

        /// 임의 개인 키 바이트 배열

        /// </summary>

        private byte[] randomPrivateKeyByteArray = null;

 

        /// <summary>

        /// 임의 개인 키 초기 값 바이트 배열

        /// </summary>

        private byte[] randomPrivateKeyInitialValueByteArray = null;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            this.Load             += Form_Load;

            this.FormClosing      += Form_FormClosing;

            this.sendButton.Click += sendButton_Click;

            this.timer.Tick       += timer_Tick;

 

            #endregion

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

 

        /// <summary>

        /// 폼 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e"></param>

        private void Form_Load(object sender, EventArgs e)

        {

            this.isServerWorking = true;

 

            IPAddress ipAddress = new IPAddress(0);

 

            this.tcpListener = new TcpListener(ipAddress, 2014);

 

            this.tcpListener.Start();

 

            this.thread = new Thread(StartServer);

 

            this.thread.Start();

 

            this.timer.Enabled = true;

 

            this.randomValue = this.random.Next(1, 9);

 

            SetRandomPrivateKeyByteArray(this.randomValue);

        }

 

        #endregion

        #region 폼을 닫을 경우 처리하기 - Form_FormClosing(sender, e)

 

        /// <summary>

        /// 폼을 닫을 경우 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_FormClosing(object sender, FormClosingEventArgs e)

        {

            if(!(this.streamWriter == null))

            {

                try

                {

                    this.streamWriter.WriteLine(Encrypt("서버를 종료합니다."));

 

                    this.streamWriter.Flush();

                }

                catch { }

            }

 

            this.isServerWorking = false;

 

            this.timer.Enabled = false;

 

            if(!(this.streamWriter == null))

            {

                this.streamWriter.Close();

            }

 

            if(!(this.networkStream == null))

            {

                this.networkStream.Close();

            }

 

            if(!(this.tcpClient == null))

            {

                this.tcpClient.Close();

            }

 

            if(!(this.tcpListener == null))

            {

                this.tcpListener.Stop();

            }

 

            if(!(this.thread == null))

            {

                this.thread.Abort();

            }

 

            Application.ExitThread();

        }

 

        #endregion

        #region 송신 버튼 클릭시 처리하기 - sendButton_Click(sender, e)

 

        /// <summary>

        /// 송신 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void sendButton_Click(object sender, EventArgs e)

        {

            if(this.networkStream != null && this.streamWriter != null)

            {

                this.streamWriter.WriteLine(Encrypt("12345abcde"));

 

                this.streamWriter.Flush();

            }

        }

 

        #endregion

        #region 타이머 틱 처리하기 - timer_Tick(sender, e)

 

        /// <summary>

        /// 타이머 틱 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void timer_Tick(object sender, EventArgs e)

        {

            SendTimeMessage();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 임의 개인 키 바이트 배열 설정하기 - SetRandomPrivateKeyByteArray(randomValue)

 

        /// <summary>

        /// 임의 개인 키 바이트 배열 설정하기

        /// </summary>

        /// <param name="randomValue">임의 값</param>

        private void SetRandomPrivateKeyByteArray(int randomValue)

        {

            randomPrivateKeyByteArray = new byte[this.privateKeyByteArray.Length];

            randomPrivateKeyInitialValueByteArray  = new byte[this.privateKeyInitialValueByteArray.Length];

 

            for(int i = 0; i < this.privateKeyByteArray.Length; i++)

            {

                int value = (int)this.privateKeyByteArray[i];

 

                randomPrivateKeyByteArray[i] = Convert.ToByte(value / randomValue);

            }

 

            for(int i = 0; i < this.privateKeyInitialValueByteArray.Length; i++)

            {

                int value = (int)this.privateKeyInitialValueByteArray[i];

 

                randomPrivateKeyInitialValueByteArray[i] = Convert.ToByte(value / randomValue);

            }

        }

 

        #endregion

        #region 메시지 박스 데이터 추가하기 - AddMessageTextBoxData(text)

 

        /// <summary>

        /// 메시지 박스 데이터 추가하기

        /// </summary>

        /// <param name="text">텍스트</param>

        private void AddMessageTextBoxData(string text)

        {

            this.messageTextBox.AppendText(text + "\r\n");

 

            this.messageTextBox.Focus();

 

            this.messageTextBox.ScrollToCaret();

        }

 

        #endregion

        #region 서버 시작하기 - StartServer()

 

        /// <summary>

        /// 서버 시작하기

        /// </summary>

        private void StartServer()

        {

            AddMessageTextBoxData("서버가 실행이 되었습니다.");

 

            while(this.isServerWorking)

            {

                try

                {

                    this.tcpClient = this.tcpListener.AcceptTcpClient();

 

                    AddMessageTextBoxData("클라이언트가 접속하였습니다.");

 

                    this.networkStream = this.tcpClient.GetStream();

 

                    this.streamWriter = new StreamWriter(this.networkStream);

                }

                catch

                {

                }

            }

        }

 

        #endregion

        #region 시간 메시지 송신하기 - SendTimeMessage()

 

        /// <summary>

        /// 시간 메시지 송신하기

        /// </summary>

        private void SendTimeMessage()

        {

            try

            {

                string messageEncrypted = Encrypt(Convert.ToString(DateTime.Now));

 

                this.streamWriter.WriteLine(messageEncrypted);

 

                this.streamWriter.Flush();

            }

            catch

            {

            }

        }

 

        #endregion

        #region 암호화 하기 - Encrypt(message)

 

        /// <summary>

        /// 암호화 하기

        /// </summary>

        /// <param name="message">메시지</param>

        /// <returns>암호화 메시지</returns>

        private string Encrypt(string message)

        {

            string messageEncrypted = null;

 

            byte[] textByteArray = UTF8Encoding.UTF8.GetBytes(message);

 

            messageEncrypted = Convert.ToBase64String

            (

                this.tripleDESCryptoServiceProvider.CreateEncryptor

                (

                    randomPrivateKeyByteArray,

                    randomPrivateKeyInitialValueByteArray

                ).TransformFinalBlock(textByteArray, 0, textByteArray.Length)

            );

 

            textByteArray = UTF8Encoding.UTF8.GetBytes(this.randomValue.ToString() + messageEncrypted);

 

            messageEncrypted = Convert.ToBase64String

            (

                this.tripleDESCryptoServiceProvider.CreateEncryptor

                (

                    this.privateKeyByteArray,

                    this.privateKeyInitialValueByteArray

                ).TransformFinalBlock(textByteArray, 0, textByteArray.Length)

            );

 

            return messageEncrypted;

        }

 

        #endregion

    }

}

 

 

[TestClient 프로젝트]

 

MainForm.cs

 

 

using System;

using System.IO;

using System.Net.Sockets;

using System.Security.Cryptography;

using System.Text;

using System.Threading;

using System.Windows.Forms;

 

namespace TestClient

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// TCP 클라이언트

        /// </summary>

        private TcpClient tcpClient;

 

        /// <summary>

        /// 네트워크 스트림

        /// </summary>

        private NetworkStream networkStream;

 

        /// <summary>

        /// 스트림 리더

        /// </summary>

        private StreamReader streamReader;

 

        /// <summary>

        /// 스레드

        /// </summary>

        private Thread thread;

 

        /// <summary>

        /// 트리플 DES 암호 서비스 공급자

        /// </summary>

        private TripleDESCryptoServiceProvider tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();

 

        /// <summary>

        /// 개인 키 바이트 배열

        /// </summary>

        private byte[] privateKeyByteArray = new byte[]

        {

            98 , 45 , 125, 56, 1 , 60 , 11, 38 ,

            123, 54 , 234, 9 , 76, 20 , 44, 7  ,

            12 , 223, 219, 95, 48, 156, 32, 239

        };

 

        /// <summary>

        /// 개인 키 초기 값 바이트 배열

        /// </summary>

        private byte[] privateKeyInitialValueByteArray = new byte[]

        {

            67, 12, 3, 41, 66, 78, 34, 123

        };

 

        /// <summary>

        /// 임의 개인 키 바이트 배열

        /// </summary>

        private byte[] randomPrivateKeyByteArray = null;

 

        /// <summary>

        /// 임의 개인 키 초기 값 바이트 배열

        /// </summary>

        private byte[] randomPrivateKeyInitialValueByteArray = null;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            Load        += Form_Load;

            FormClosing += Form_FormClosing;

 

            #endregion

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

 

        /// <summary>

        /// 폼 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_Load(object sender, EventArgs e)

        {

            try

            {

                this.tcpClient = new TcpClient("127.0.0.1", 2014);

 

                AddMessageTextBoxData("서버에 접속 했습니다.");

 

                this.networkStream = this.tcpClient.GetStream();

 

                this.streamReader = new StreamReader(this.networkStream);

 

                this.thread = new Thread(ReceiveMessage);

 

                this.thread.Start();

            }

            catch

            {

                AddMessageTextBoxData("서버에 접속하지 못 했습니다.");

            }

        }

 

        #endregion

        #region 폼을 닫을 경우 처리하기 - Form_FormClosing(sender, e)

 

        /// <summary>

        /// 폼을 닫을 경우 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_FormClosing(object sender, FormClosingEventArgs e)

        {

            try

            {

                if(!(this.streamReader == null))

                {

                    this.streamReader.Close();

                }

 

                if(!(this.networkStream == null))

                {

                    this.networkStream.Close();

                }

 

                if(!(this.tcpClient == null))

                {

                    this.tcpClient.Close();

                }

 

                if(!(this.thread == null))

                {

                    this.thread.Abort();

                }

            }

            catch

            {

                return;

            }

 

            Application.ExitThread();

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 메시지 텍스트 박스 데이터 추가하기 - AddMessageTextBoxData(text)

 

        /// <summary>

        /// 메시지 텍스트 박스 데이터 추가하기

        /// </summary>

        /// <param name="text">텍스트</param>

        private void AddMessageTextBoxData(string text)

        {

            this.messageTextBox.AppendText(text + "\r\n");

 

            this.messageTextBox.Focus();

 

            this.messageTextBox.ScrollToCaret();

        }

 

        #endregion

        #region 임의 개인 키 바이트 배열 설정하기 - SetRandomPrivateKeyByteArray(randomValue)

 

        /// <summary>

        /// 임의 개인 키 바이트 배열 설정하기

        /// </summary>

        /// <param name="randomValue">임의 값</param>

        private void SetRandomPrivateKeyByteArray(int randomValue)

        {

            this.randomPrivateKeyByteArray             = new byte[this.privateKeyByteArray.Length];

            this.randomPrivateKeyInitialValueByteArray = new byte[this.privateKeyInitialValueByteArray.Length];

 

            for(int i = 0; i < this.privateKeyByteArray.Length; i++)

            {

                int value = (int)this.privateKeyByteArray[i];

 

                this.randomPrivateKeyByteArray[i] = Convert.ToByte(value / randomValue);

            }

 

            for(int i = 0; i < this.privateKeyInitialValueByteArray.Length; i++)

            {

                int value = (int)this.privateKeyInitialValueByteArray[i];

 

                this.randomPrivateKeyInitialValueByteArray[i] = Convert.ToByte(value / randomValue);

            }

        }

 

        #endregion

        #region 암호화 풀기 - Decrypt(messageEncrypted)

 

        /// <summary>

        /// 암호화 풀기

        /// </summary>

        /// <param name="messageEncrypted">암호화 메시지</param>

        /// <returns>메시지</returns>

        private string Decrypt(string messageEncrypted)

        {

            string message = null;

 

            byte[] messageEncryptedByteArrat = Convert.FromBase64String(messageEncrypted);

 

            message = UTF8Encoding.UTF8.GetString

            (

                this.tripleDESCryptoServiceProvider.CreateDecryptor

                (

                    this.privateKeyByteArray,

                    this.privateKeyInitialValueByteArray

                ).TransformFinalBlock(messageEncryptedByteArrat, 0, messageEncryptedByteArrat.Length)

            );

 

            SetRandomPrivateKeyByteArray(Convert.ToInt32(message.Substring(0, 1)));

 

            messageEncryptedByteArrat = Convert.FromBase64String(message.Substring(1, message.Length - 1));

 

            message = UTF8Encoding.UTF8.GetString

            (

                this.tripleDESCryptoServiceProvider.CreateDecryptor

                (

                    this.randomPrivateKeyByteArray,

                    this.randomPrivateKeyInitialValueByteArray

                ).TransformFinalBlock(messageEncryptedByteArrat, 0, messageEncryptedByteArrat.Length)

            );

 

            return message;

        }

 

        #endregion

        #region 메시지 수신하기 - ReceiveMessage()

 

        /// <summary>

        /// 메시지 수신하기

        /// </summary>

        private void ReceiveMessage()

        {

            try

            {

                while(true)

                {

                    if(this.networkStream.CanRead)

                    {

                        string messageEncrypted = this.streamReader.ReadLine();

 

                        if(messageEncrypted.Length > 0)

                        {

                            string message = Decrypt(messageEncrypted);

 

                            AddMessageTextBoxData(message);

                        }

                    }

                }

            }

            catch

            {

            }

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요