C# Socket 客戶端服務端的創建、連接以及發送回覆

最近簡單學習了一下C# Socket的一些用法,在這裏稍作總結;

瞭解過Socket的,應該都知道記可以做服務端開發也可以做客戶端開發,在這裏就簡單介紹一下;

主要是客戶端服務端的創建,連接,發送等內容;

做之前,先說一下這個結構,我們需要連接,發送等邏輯,爲了方便測試,我們需要建兩個項目;

建兩個控制檯應用程序,一個服務端,一個客戶端;

首先,我們在服務端項目中建一個Server.cs;

引入需要的程序集; 

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
    public class Server {
        private string m_host;
        private int m_port;
        private int m_backlog;
        private Socket m_socket;

        /// <summary>
        /// 傳入參數默認加入數量限制參數
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        public Server(string host, int port) : this(host, port, 10) {
            
        }

        /// <summary>
        /// 創建一個server對象
        /// </summary>
        /// <param name="host">ip地址</param>
        /// <param name="port">端口號</param>
        /// <param name="backlog">連接數量</param>
        public Server(string host, int port, int backlog) {
            m_host = host;
            m_port = port;
            m_backlog = backlog;
            m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        /// <summary>
        /// 開啓服務器
        /// 之後開啓一個後臺運行的線程, 用於監聽客戶端的請求
        /// </summary>
        public void Begin() {
            m_socket.Bind(new IPEndPoint(IPAddress.Parse(m_host), m_port));
            m_socket.Listen(m_backlog);
            Console.WriteLine("Server Begin Success");

            Thread thread = new Thread(Accept);
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 監聽客戶端的連接,並打印出客戶端的Ip等相關信息
        /// 同時在開啓一個後臺線程用於監聽客戶端向服務端發送的信息並接收
        /// </summary>
        private void Accept() {
            //接受客戶端的方法,會掛起當前線程
            Socket client = m_socket.Accept();
            IPEndPoint point = client.RemoteEndPoint as IPEndPoint;
            Console.WriteLine(point.Address + " - " + point.Port + " - 連接成功;");

            Thread thread = new Thread(Receive);
            thread.IsBackground = true;
            thread.Start(client);

            Accept();
        }

        /// <summary>
        /// 處理接收來自客戶端發過來的信息,同時向當前客戶端回覆信息
        /// 在這裏採用UTF8編碼格式,客戶端服務端要統一,否則發送與接收過程會出現編碼問題
        /// </summary>
        /// <param name="obj">當前客戶端對象</param>
        private void Receive(object obj) {
            var client = obj as Socket;
            IPEndPoint point = client.RemoteEndPoint as IPEndPoint;
            try {
                byte[] msg = new byte[1024];
                var len = client.Receive(msg);
                string msgStr = Encoding.UTF8.GetString(msg, 0, len);
                Console.WriteLine(point.Address + ":    " + msgStr);
                client.Send(Encoding.UTF8.GetBytes("迴應:   " + msgStr));

                Receive(client);
            } catch {
                Console.WriteLine(point.Address + ":    客戶端已斷開連接");
            }
            
        }
    }

然後我們在Main(string[] args)中調用;

    static void Main(string[] args) {
        string ip = "***.***.***.***";
        int port = 12312;
        Server.Server server = new Server.Server(ip, port);
        server.Begin();
        Console.ReadLine();
    }

點擊運行,這樣,我們的服務器就跑起來了;

下面我們來在客戶端項目中創建Client.cs;

引入必要的程序集;

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
    public class Client {

        private const int TIME_OUT = 3000;

        private string m_host;
        private int m_port;
        private Socket m_socket;

        /// <summary>
        /// 創建一個客戶端對象
        /// </summary>
        /// <param name="host">ip地址</param>
        /// <param name="port">對應端口號</param>
        public Client(string host, int port) {
            m_host = host;
            m_port = port;
            m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        /// <summary>
        /// 判斷當前是否有效連接
        /// </summary>
        /// <returns></returns>
        public bool IsConnect() {
            return m_socket != null && m_socket.Connected;
        }

        /// <summary>
        /// 開始連接服務器,設置超時時間(測試方便使用)
        /// 連接結束後,開啓一個後臺線程用於監聽接收服務端的發來的消息
        /// </summary>
        public void Connect() {
            Thread thread = new Thread(() => {
                IAsyncResult asyncResult = m_socket.BeginConnect(new IPEndPoint(IPAddress.Parse(m_host), m_port), null, null);
                int time = 0;
                while(time < TIME_OUT && !asyncResult.IsCompleted) {
                    Thread.Sleep(100);
                    time += 100;
                    Console.WriteLine("Connecting ...");
                }
                if(asyncResult.IsCompleted) {
                    if(time >= TIME_OUT) {
                        //todo:超時
                        Console.WriteLine("Client Connect Timeout");
                    } else {
                        if(IsConnect()) {
                            Console.WriteLine("Client Connect Success");
                        } else {
                            Console.WriteLine("Client Connect Faile");
                        }
                    }
                }

                Thread t = new Thread(Receive);
                t.IsBackground = true;
                t.Start();
            });
            thread.Start();
        }

        /// <summary>
        /// 當前連接有效的情況下,向服務端發送信息(UTF8)
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg) {
            if(!IsConnect()) {
                Console.WriteLine("Client Connect Faile");
                return;
            }
            var msgByte = Encoding.UTF8.GetBytes(msg);
            m_socket.Send(msgByte);
        }

        /// <summary>
        /// 處理服務器發過來的信息(UTF8)
        /// </summary>
        private void Receive() {
            while(true) {
                try{
                    byte[] msg = new byte[1024];
                    int len = m_socket.Receive(msg);
                    Console.WriteLine("Server:" + Encoding.UTF8.GetString(msg, 0, len));

                    Receive();
                }
                catch{
                    Console.WriteLine("服務端連接無效");
                    break;
                }
            }
            
        }
    }

創建好之後,我們把客戶端也開起來;

    static void Main(string[] args) {
        string ip = "***.***.***.***";
        int port = 12312;
        Client.Client client = new Client.Client(ip, port);
        client.Connect();

        Console.WriteLine("Please input message:");
        string msg = Console.ReadLine();
        while(msg != "quit") {
            if(msg != "") {
                client.Send(msg);
            } else {
                Console.WriteLine("This is Empty");
            }
            msg = Console.ReadLine();
        }

        Console.ReadLine();
    }

下面我們進行測試:

本文爲原創作品,如有雷同,純屬巧合;

文中若有不當之處,歡迎指正,共同學習,謝謝;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章