Unity3d 封装Socket创建简单网络

Posted 不伪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的沾包, 闭包,需要进一步处理

 

以上是关于Unity3d 封装Socket创建简单网络的主要内容,如果未能解决你的问题,请参考以下文章

011.socket函数错误封装处理

Unity3D网络通讯--Socket通讯之Tcp通讯

什么是Socket?简单点,通俗易懂的?

GJM: Unity3D基于Socket通讯例子

PHP实现简单的socket与异步应用

Python的网络编程socket