1. 程式人生 > >利用C#進行Socket通訊程式設計之二:一個例項

利用C#進行Socket通訊程式設計之二:一個例項

    利用晚上這點閒暇時間,寫了一個Socket通訊的小例項,該例項包含伺服器端和客戶端。其基本工作流程是:當伺服器啟動服務以後,客戶端進行連線,如果連線成功,則使用者可以在傳送訊息框中輸入待發送的訊息,然後點選“Send”按鈕後向伺服器傳送訊息,伺服器在收到訊息後立即向該客戶端傳送接收成功訊息。其基本效果如圖1.1和圖1.2所示(注:下面兩幅圖於次日補上):

圖1.1  伺服器執行效果圖

圖1.2  客戶端執行效果圖

    現將伺服器和客戶端部分程式碼貼出來,由於程式碼較簡單,基本沒有註釋,並在此特別說明,該例項僅僅是一個簡單的示例,其中的程式碼仍有進一步修改優化空間,同時亦歡迎各位朋友批評指正。
    伺服器程式碼部分:
using System;
using System.Text;
using System.Windows.Forms;

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

namespace SocketServer
{
    public partial class frmServer : Form
    {
        private Thread m_serverThread;
        private Socket m_serverSocket;
        private string m_serverIP;
        private int m_serverPort;

        public delegate void ReceiveMessageDelegate(Client client);
        ReceiveMessageDelegate receiveMessageDelegate;
       
        public frmServer()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void frmServer_Load(object sender, EventArgs e)
        {
            string[] addresses = GetLocalAddresses();
            cmbIP.Items.Clear();
            if (addresses.Length > 0)
            {
                for (int i = 0; i < addresses.Length; i++)
                {
                    cmbIP.Items.Add(addresses[i]);
                }
                cmbIP.Text = (string)cmbIP.Items[0];
            }

            txtPort.Text = "8899";
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            m_serverIP = cmbIP.Text;
            m_serverPort = Int32.Parse(txtPort.Text);

            Start();
            btnStart.Enabled = false;
            btnStop.Enabled = true;
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            Stop();
            btnStart.Enabled = true;
            btnStop.Enabled = false;
        }

        /// <summary>
        /// 開始服務
        /// </summary>
        private void Start()
        {
            try
            {
                m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(m_serverIP), m_serverPort);
                m_serverSocket.Bind(localEndPoint);
                m_serverSocket.Listen(10);

                m_serverThread = new Thread(new ThreadStart(ReceiveAccept));
                m_serverThread.Start();

                this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Server started.");
            }
            catch (SocketException se)
            {
                throw new Exception(se.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 停止服務
        /// </summary>
        private void Stop()
        {
            try
            {
                m_serverThread.Abort(); // 執行緒終止
                m_serverSocket.Close(); // Socket Close

                this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Server stoped.");
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private void ReceiveAccept()
        {
            while (true)
            {
                Client client = new Client();

                try
                {
                    client.ClientSocket = m_serverSocket.Accept();
                    this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Client[" + client.ClientSocket.RemoteEndPoint.ToString() + "] connected.");

                    receiveMessageDelegate = new ReceiveMessageDelegate(ReceiveMessages);
                    receiveMessageDelegate.BeginInvoke(client, ReceiveMessagesCallback, "");
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        private void ReceiveMessages(Client client)
        {
            while (true)
            {
                byte[] receiveBuffer = new byte[1024];

                client.ClientSocket.Receive(receiveBuffer);

                string strReceiveData = Encoding.Unicode.GetString(receiveBuffer);
                if (!string.IsNullOrEmpty(strReceiveData))
                {
                    this.AddRunningInfo(">> Receive data from [" + client.ClientSocket.RemoteEndPoint.ToString()+ "]:" + strReceiveData);
                    string strSendData = "OK. The content is:" + strReceiveData;
                    int sendBufferSize = Encoding.Unicode.GetByteCount(strSendData);
                    byte[] sendBuffer = new byte[sendBufferSize];
                    sendBuffer = Encoding.Unicode.GetBytes(strSendData);

                    client.ClientSocket.Send(sendBuffer);
                }
            }
        }

        private void ReceiveMessagesCallback(IAsyncResult AR)
        {
            receiveMessageDelegate.EndInvoke(AR);
        }

        /// <summary>
        /// 將執行資訊加入顯示列表
        /// </summary>
        private void AddRunningInfo(string message)
        {
            lstRunningInfo.BeginUpdate();
            lstRunningInfo.Items.Insert(0, message);

            if (lstRunningInfo.Items.Count > 100)
            {
                lstRunningInfo.Items.RemoveAt(100);
            }

            lstRunningInfo.EndUpdate();
        }

        /// <summary>
        /// 獲取本機地址列表
        /// </summary>
        public string[] GetLocalAddresses()
        {
            // 獲取主機名
            string strHostName = Dns.GetHostName();

            // 根據主機名進行查詢
            IPHostEntry iphostentry = Dns.GetHostEntry(strHostName);

            string[] retval = new string[iphostentry.AddressList.Length];

            int i = 0;
            foreach (IPAddress ipaddress in iphostentry.AddressList)
            {
                retval[i] = ipaddress.ToString();
                i++;
            }
            return retval;
        }
    }

    /// <summary>
    /// 客戶端會話資訊類
    /// </summary>
    public class Client
    {
        Socket m_clientSocket;

        public Client() { }

        public Socket ClientSocket
        {
            get { return m_clientSocket; }
            set { this.m_clientSocket = value; }
        }
    }
}

    客戶端部分:
using System;
using System.Text;
using System.Windows.Forms;

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

namespace SocketClient
{
    public partial class frmClient : Form
    {
        private Socket m_clientSocket;
        private byte[] m_receiveBuffer = new byte[1024];

        public frmClient()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void frmClient_Load(object sender, EventArgs e)
        {
            txtIP.Text = "172.18.20.234";
            txtPort.Text = "8899";
        }

        /// <summary>
        /// 連線伺服器
        /// </summary>
        private void btnConnect_Click(object sender, EventArgs e)
        {
            string serverIP = txtIP.Text;
            int serverPort = Int32.Parse(txtPort.Text);

            m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(serverIP),serverPort);

            try
            {
                m_clientSocket.Connect(remoteEndPoint);
                if (m_clientSocket.Connected)
                {
                    m_clientSocket.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);

                    btnConnect.Enabled = false;
                    btnDisconnect.Enabled = true;

                    this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Client connect server success.");
                }
            }
            catch (Exception)
            {
                this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Client connect server fail.");
                m_clientSocket = null;
            }
        }

        /// <summary>
        /// 斷開連線
        /// </summary>
        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            if (m_clientSocket != null)
            {
                m_clientSocket.Close();

                btnConnect.Enabled = true;
                btnDisconnect.Enabled = false;
                btnSend.Enabled = false;

                this.AddRunningInfo(">> " + DateTime.Now.ToString() + " Client disconnected.");
            }
        }

        /// <summary>
        /// 傳送資訊
        /// </summary>
        private void btnSend_Click(object sender, EventArgs e)
        {
            string strSendData = txtSend.Text;
            byte[] sendBuffer = new byte[1024];
            sendBuffer = Encoding.Unicode.GetBytes(strSendData);

            if (m_clientSocket != null)
            {
                m_clientSocket.Send(sendBuffer);
            }
        }

        private void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                int REnd = m_clientSocket.EndReceive(ar);
                string strReceiveData = Encoding.Unicode.GetString(m_receiveBuffer, 0, REnd);
                this.HandleMessage(strReceiveData);
                m_clientSocket.BeginReceive(m_receiveBuffer, 0, m_receiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 處理接收到的資料
        /// </summary>
        private void HandleMessage(string message)
        {
            message = message.Replace("/0", "");
            if (!string.IsNullOrEmpty(message))
            {
                this.AddRunningInfo(">> Receive Data from server:" + message);
            }
        }

        private void AddRunningInfo(string message)
        {
            lstRunningInfo.BeginUpdate();
            lstRunningInfo.Items.Insert(0, message);

            if (lstRunningInfo.Items.Count > 100)
            {
                lstRunningInfo.Items.RemoveAt(100);
            }

            lstRunningInfo.EndUpdate();
        }

        private void txtSend_TextChanged(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtSend.Text) && m_clientSocket!=null)
            {
                btnSend.Enabled = true;
            }
            else
            {
                btnSend.Enabled = false;
            }
        }
    }
}