18U3D Socket实现简易通讯

Posted zpy1993-09

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18U3D Socket实现简易通讯相关的知识,希望对你有一定的参考价值。

  Step1:创建工具类 NetWorkManger 实现服务器和客户端的连接和消息的发送

  

创建该类需要导入命名空间:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
将工具类设置为单例类:
public class NetWorkManger
{
    #region 单例类
    private static NetWorkManger instance;
    private NetWorkManger ()
    {
    }
    public static NetWorkManger Instance {
        get {
            if (instance == null) {
                instance = new NetWorkManger ();
            }
            return instance;
        }
    }
    #endregion
/// <summary>
    /// 定义一个委托类型,只要方法类型为该类型,即可通过该委托进行自动回调(这里用在发送消息和接收回调)
    /// </summary>
    public delegate void MyCallBack (string msg);

 服务器端 方法

#region 服务器端

    /*
     * 服务器的创建流程
     * 1、创建服务器
     * 2、等待客户端连接
     * 3、发送消息
     * 4、接收消息
     * 
     * 使用到的socket中的哪些方法
     * 1、创建套接字(socket)的方法
     * 2、绑定端口号和IP的方法
     * 3、监听连接的方法
     * 4、接收客户端请求的方法(Accept)
     * 5、收发消息的方法
    */

    /// <summary>
    /// 服务器委托回调对象,主要向外界传送消息,
    /// 用作服务器向外传值
    /// </summary>
    MyCallBack m_serverCallBack;
    /// <summary>
    /// 服务器端套接字对象
    /// </summary>
    Socket m_serverSocket;
    /// <summary>
    /// 服务器端的输入输出缓冲区域
    /// </summary>
    byte[] m_serverBuffer;

    /// <summary>
    /// 初始化服务器
    /// </summary>
    /// <param name="userCallBack">外界传入的方法</param>
    public void ServerInit (MyCallBack userCallBack)
    {
        m_serverCallBack = userCallBack;
        //实例化输入输出的数组
        m_serverBuffer = new byte[1024];
        //实例化socket
        m_serverSocket = new Socket (
            //使用IP地址类型为IPv4
            AddressFamily.InterNetwork,
            //套接字类型为TCP的流式传输
            SocketType.Stream,
            //选取协议为TCP协议
            ProtocolType.Tcp
        );
        /// <summary>
        /// 绑定IP地址和端口号
        /// IPAddress.Any:表示接受所有连接的IP地址
        /// 34567:表示端口号,IP表示是哪个电脑,
        ///        端口指哪个服务(哪个应用)
        /// </summary>
        IPEndPoint point = 
            new IPEndPoint (IPAddress.Any, 34567);
        //将节点绑定到socket上
        m_serverSocket.Bind (point);
        //开始监听(如果监听成功,服务器就启动成功了,
        //10表示能接受到的最大连接数)
        m_serverSocket.Listen (10);
        //将服务器启动成功的消息发送出去
        m_serverCallBack ("服务器启动成功");
        //开始接收,进入等待客户端的连接的状态
        //第一个参数:这是一个方法名字,等到有客户端连接时
        //          自动回调的方法,这个方法需要传入一个
        //          IAsyncResult类型的参数,这个方法一旦
        //          开启,就会开启一个子线程,直到有人连接
        //          会通知主线程,通知的内容就是这个IAsyncResult
        //第二个参数:对应当前监听连接的socket
        m_serverSocket.BeginAccept (
            ServerAccept, m_serverSocket
        );
    }

    /// <summary>
    /// 当服务器接收到用户的连接请求时的回调方法
    /// </summary>
    /// <param name="ar">子线程向主线程传递
    /// 的有客户端连接的信息</param>
    void ServerAccept (IAsyncResult ar)
    {
        
        //当客户端连接时,获取到当前子线程中等待的socket
        m_serverSocket = ar.AsyncState as Socket;
        //接收结果,这是一个新的socket
        Socket workingSocket =
            m_serverSocket.EndAccept (ar);
        //开始基于建立新的socket进行收发消息
        workingSocket.BeginReceive (
            //收发缓存区
            m_serverBuffer,
            //起始位置
            0,
            //接收数据的长度
            m_serverBuffer.Length,
            //接收过程中是否包含特殊标记
            SocketFlags.None,
            //接收到消息后的回调方法
            ServerReceive,
            //当前的套接字状态
            workingSocket
        );
        //尾递归
        m_serverSocket.BeginAccept (
            ServerAccept, m_serverSocket);
    }

    /// <summary>
    /// 服务器接收到消息的回调方法
    /// </summary>
    /// <param name="ar">Ar.</param>
    void ServerReceive (IAsyncResult ar)
    {
        Socket workingSocket = ar.AsyncState as Socket;
        //接收到的字节数据
        int count = workingSocket.EndReceive (ar);
        //将字节数据转成字符串
        string msgResult = 
            UTF8Encoding.UTF8.GetString (m_serverBuffer);
        //回调
        m_serverCallBack ("收到了" + count + "字节数据");
        m_serverCallBack (msgResult);
        m_serverBuffer = new byte[1024];
        //尾递归
        workingSocket.BeginReceive (
            m_serverBuffer,
            0,
            m_serverBuffer.Length,
            SocketFlags.None,
            ServerReceive,
            workingSocket
        );
    }
    #endregion
 

客户端方法封装

#region 客户端

    /// <summary>
    /// 客户端套接字.
    /// </summary>
    Socket m_clientSocket;

    /// <summary>
    /// 客户端委托回调
    /// </summary>
    MyCallBack m_clientCallback;

    /// <summary>
    /// 客户端数据缓存区域
    /// </summary>
    byte[] m_clientBuffer;

    /// <summary>
    /// 客户端连接服务端的方法
    /// </summary>
    /// <param name="ip">要连接的IP地址</param>
    /// <param name="port">端口号</param>
    /// <param name="uerCallBack">消息回调</param>
    public void ClientConnect (
        string ip, int port, MyCallBack uerCallBack)
    {
        m_clientSocket = new Socket (
            AddressFamily.InterNetwork,
            SocketType.Stream,
            ProtocolType.Tcp
        );
        //初始化客户端数据缓存区域
        m_clientBuffer = new byte[1024];

        //连接服务器,IPAddress.Parse:解析IP
        m_clientSocket.Connect (
            IPAddress.Parse (ip), port);
        //消息回调
        m_clientCallback = uerCallBack;
        m_clientCallback ("服务器连接成功");
        //开始接收消息
        m_clientSocket.BeginReceive (
            m_clientBuffer,
            0,
            m_clientBuffer.Length,
            SocketFlags.None,
            ClinetReceive,
            m_clientSocket
        );
    }

    /// <summary>
    /// 客户端接收到消息后回调的方法
    /// </summary>
    /// <param name="ar">Ar.</param>
    void ClinetReceive (IAsyncResult ar)
    {
        Socket workingSocket = ar.AsyncState as Socket;
        //接收到的字节数目
        int count = workingSocket.EndReceive (ar);
        //将接收到的数据转成字符串
        string msgResult =
            UTF8Encoding.UTF8.GetString (m_clientBuffer);
        m_clientCallback ("收到了" + count + "字节数据");
        //对外进行回调
        m_clientCallback (msgResult);
        //重置一下buffer
        m_clientBuffer = new byte[1024];
        //开始接收消息(递归接收)
        m_clientSocket.BeginReceive (
            m_clientBuffer,
            0,
            m_clientBuffer.Length,
            SocketFlags.None,
            ClinetReceive,
            workingSocket
        );
    }

    /// <summary>
    /// 客户端发送消息的方法
    /// </summary>
    /// <param name="msg">Message.</param>
    public void ClientSend (string msg)
    {
        //将要发送的内容转成字节数组
        m_clientBuffer = 
            UTF8Encoding.UTF8.GetBytes (msg);
        //开始发送
        m_clientSocket.BeginSend (
            m_clientBuffer,
            0,
            m_clientBuffer.Length,
            SocketFlags.None,
            //数据发送成功之后的回调
            SendSucces,
            m_clientSocket
        );
    }

    /// <summary>
    ///  客户端发送数据成功的回调方法
    /// </summary>
    /// <param name="ar">Ar.</param>
    void SendSucces (IAsyncResult ar)
    {
        //发送成功,获得发送成功的socket
        Socket workingSocket = ar.AsyncState as Socket;
        //结束发送
        workingSocket.EndSend (ar);
    }
    #endregion

step2:创建服务器场景-Server(接收消息)

public class ServerScript : MonoBehaviour
{
    Text m_text;
    string m_currentMsg;
    void Awake ()
    {
        //保证程序后台运行
        Application.runInBackground = true;
    }
    void Start ()
    {
        m_text = GameObject.Find ("Text").GetComponent<Text> ();
        //创建服务器
        NetWorkManger.Instance.ServerInit ((string msg) => {
            //将服务器传递过来的数据接收一下
            m_currentMsg = msg;
        });
        m_text.text = m_currentMsg;
    }
    void Update ()
    {
        //将接受到的数据放到Text中
        m_text.text = m_currentMsg;
    }

step3:创建客户端服务器-Client(发送消息)

 

public class ServerScript : MonoBehaviour
{

    Text m_text;

    string m_currentMsg;

    void Awake ()
    {
        //保证程序后台运行
        Application.runInBackground = true;
    }

    void Start ()
    {
        m_text = GameObject.Find ("Text").GetComponent<Text> ();
        //创建服务器
        NetWorkManger.Instance.ServerInit ((string msg) => {
            //将服务器传递过来的数据接收一下
            m_currentMsg = msg;
        });
        m_text.text = m_currentMsg;
    }

    void Update ()
    {
        //将接受到的数据放到Text中
        m_text.text = m_currentMsg;
    }
}

 

以上是关于18U3D Socket实现简易通讯的主要内容,如果未能解决你的问题,请参考以下文章

Java Socket可配置简易通讯器

golang代码片段(摘抄)

Socket编程一实现简易的聊天功能以及文件传输

实现简易通讯录(动态增长版)

通过socket实现http通讯代码理解

java代码实现socket接口通讯(堵塞I/O)