Unity3d網絡總結(三) 封裝Socket創建簡單網絡


北京又在打雷下大雨了,學習Unity以來,越來越感興趣,情不自禁的想要學習更多知識

這次自己搭建一個Socket模塊,比較基礎,適合新手學習,詳細介紹Socket的搭建過程,同樣會把詳細過程在代碼里進行注釋~

在搭建Socket過程中,需要創建以下幾個常用的方法:

1.創建套接字(socket)

2.綁定Ip和端口

3.監聽方法

4.接收客戶端請求的方法

5.收發消息的方法

創建SocketManger管理類

把客戶端與服務端代碼都寫在新建的SocketManger里,並把SocketManger寫成單例,方便調用

using System.Net;
//引入套接字協議類
using System.Net.Sockets;
using System;
using System.Text;

public class SocketManager {
    #region 單例類
    private static SocketManager instance;
    private SocketManager()
    {
    }
    public static SocketManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new SocketManager();
            }
            return instance;
        }
    }
    #endregion

    public delegate void MyCallBack(string msg);    //聲明一個委托類型,在服務器和客戶端工作的時候,會使用這個回調方法反饋當前交互的具體情況

服務端代碼

#region 服務器代碼
    /* 創建服務器
     * 等待客戶端的連接
     * 接受消息
     */
    Socket serverSocket;             //創建服務器的套接字對象
    MyCallBack serverCallBack;       //定義一個服務器使用的回調委托對象
    byte[] serverBuffer;             //數據緩存區  文字,音頻,視頻,圖片...

    public void InitServer(MyCallBack callBack)
    {
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //參數(1.使用IP地址的類型 2.套接字類型,使用TCP的流式傳輸  3.使用TCP協議)
        serverBuffer = new byte[1024];    //初始化緩沖區的大小
        serverCallBack = callBack;        //綁定初始化服務器的回調方法

        IPEndPoint point = new IPEndPoint(IPAddress.Any, 34567);      //參數(1.地址,代表一台電腦, 2.端口號表示一個應用)
        serverSocket.Bind(point);    //綁定地址節點
        serverSocket.Listen(10);       //開始監聽, 一旦監聽成功,服務器就啟動,10代表最大監聽數量 
        serverCallBack("服務器啟動成功");

        //服務器開始進入等待用戶連接的狀態
        //開辟一條子線程實時監測是否有人連接
        //一旦有客戶端連接,立馬通知主線程,通知內容會以IAsyncResult 返回,連接者的所有信息
        serverSocket.BeginAccept(ServerAccept, serverSocket);
    }

    //服務器開始接收的方法
    void ServerAccept(IAsyncResult ar)
    {
        serverSocket = ar.AsyncState as Socket;     //拿到當前連接服務器的Socket 對象
        Socket workingSocket = serverSocket.EndAccept(ar);         //將當前的Socket的全部信息交給一個新的Socket處理

        workingSocket.BeginReceive(serverBuffer, 0, serverBuffer.Length, SocketFlags.None,ServerReceive, workingSocket);  //(數據收發緩存區,起始位置,長度,不分類型,全部接收, 接受消息之后的回調,當前Socket的狀態)

        serverSocket.BeginAccept(ServerAccept, serverSocket);      //尾遞歸
    }
    //服務器接收消息之后的回調方法
    void ServerReceive(IAsyncResult ar)
    {
        Socket workingSorket = ar.AsyncState as Socket;
        int size=workingSorket.EndReceive(ar);   //拿到接收到的數據一共有多少字節
        string str = Encoding.UTF8.GetString(serverBuffer);    //將接收到的byte數組轉換成字符串
        serverCallBack("接收到了" + size + "字節");
        serverCallBack(str);       
        workingSorket.BeginReceive(serverBuffer, 0, serverBuffer.Length, SocketFlags.None, ServerReceive, workingSorket);   //尾遞歸
    }
    #endregion

 客戶端代碼

#region
    Socket clientSocket;
    MyCallBack clientCallBack;
    byte[] clientBuffer;
    
    //客戶端連接服務器的方法
    public void ClientConnectServer(string ip,int port,MyCallBack callBack)
    {
        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        clientBuffer = new byte[1024];
        clientCallBack = callBack;

        clientSocket.Connect(IPAddress.Parse(ip),port);      //連接服務器
        clientCallBack("連接服務器成功");
        clientSocket.BeginReceive(clientBuffer, 0, clientBuffer.Length, SocketFlags.None,ClientReceive, clientSocket);
    }

    void ClientReceive(IAsyncResult ar)
    {
        Socket WorkingSocket = ar.AsyncState as Socket;
        int size=WorkingSocket.EndReceive(ar);   //接收多少字節
        string msg= Encoding.UTF8.GetString(clientBuffer);
        clientCallBack("接收了"+size+"字節");
        clientCallBack(msg);
        clientSocket.BeginReceive(clientBuffer, size, clientBuffer.Length, SocketFlags.None, ClientReceive, WorkingSocket);
    }

    //客戶端發送消息的方法
    public void ClientSendMsg(string msg)
    {
        byte[] buffer= Encoding.UTF8.GetBytes(msg);
        clientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallBack, clientSocket);
    }
    void SendCallBack(IAsyncResult ar)
    {
        Socket workingSocket = ar.AsyncState as Socket;
        workingSocket.EndSend(ar);
        clientCallBack("發送完成");
    }

#endregion

簡單的Socket搭建完成,但是有一點小Bug,服務器進入等待用戶連接狀態后,會開辟子線程實時檢測,沒有關閉這條線程,因此在搭建服務器的腳本,可以在Start方法里寫一個方法,在程序退出時關閉這條線程! 這個方法在關閉程序時自動調用

 

private void OnApplicationQuit()
    {
        serverSocket.Shutdown(SocketShutdown.Both);
        serverSocket.Close();
    }

簡單的Socket搭建完了,當然這只是非常基礎的Socket傳遞,在實際使用中,還要考慮很多問題,比如Socket的沾包, 閉包,需要進一步處理

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM