zoukankan      html  css  js  c++  java
  • Unity 网络编程(Socket)应用

    服务器端的整体思路:

    1、初始化IP地址和端口号以及套接字等字段;

    2、绑定IP启动服务器,开始监听消息  socketServer.Listen(10);

    3、开启一个后台线程接受客户端的连接 socketServer.Accept(),这里需要注意的是服务器端有两个Socket,一个负责监听,另一个负责传输消息,分工明确;

    4、接受客户端消息  socketMsg.Receive();

    5、向客户端发送消息 Send(bySendArray);

    6、当然还应该包括信息显示方法和系统的退出方法。

    /***
     * 
     * 
     *  服务器端 
     * 
     */
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    using System.Text;
    using System.Threading;
    using System.Net;
    using System.Net.Sockets;
    using UnityEngine.UI;
    using System;
    
    public class Server : MonoBehaviour
    {
        public InputField InpIPAdress;                              //IP地址
        public InputField InpPort;                                  //端口号
        public InputField InpDisplayInfo;                           //显示信息
        public InputField InpSendMsg;                               //发送信息
        public Dropdown Dro_IPList;                                 //客户端的IP列表
    
        private Socket socketServer;                                //服务端套接字
        private bool IsListionContect = true;                              //是否监听
        private StringBuilder _strDisplayInfo = new StringBuilder();//追加信息
        private string _CurClientIPValue = string.Empty;            //当前选择的IP地址
        //保存客户端通讯的套接字
        private Dictionary<string, Socket> _DicSocket = new Dictionary<string, Socket>();
        //保存DropDown的数据,目的为了删除节点信息
        private Dictionary<string, Dropdown.OptionData> _DicDropdowm = new Dictionary<string, Dropdown.OptionData>();
    
        // Start is called before the first frame update
        void Start()
        {
            //控件初始化
            InpIPAdress.text = "127.0.0.1";
            InpPort.text = "1000";
            InpSendMsg.text = string.Empty;
            
            //下拉列表处理
            Dro_IPList.options.Clear();                         //清空列表信息
            //添加一个空节点
            Dropdown.OptionData op = new Dropdown.OptionData();
            op.text = "";
            Dro_IPList.options.Add(op);
        }
    
        /// <summary>
        /// 退出系统
        /// </summary>
        public void ExitSystem()
        {
            //退出会话Socket
    
            //退出监听Socket
            if (socketServer != null)
            {
                try
                {
                    socketServer.Shutdown(SocketShutdown.Both);     //关闭连接
                }
                catch (Exception)
                {
                    
                    throw;
                }
                socketServer.Close();                           //清理资源
            }
            Application.Quit();
        }
    
        /// <summary>
        /// 获取当前好友
        /// </summary>
        public void GetCurrentIPInformation()
        {
            //选择玩家当前列表
            _CurClientIPValue = Dro_IPList.options[Dro_IPList.value].text;
        }
    
        /// <summary>
        /// 服务端开始监听
        /// </summary>
        public void EnableServerReady()
        { 
            //需要绑定地址和端口号
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(InpIPAdress.text), Convert.ToInt32(InpPort.text));
            //定义监听Socket
            socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绑定
            socketServer.Bind(endPoint);
    
            //开始socket监听
            socketServer.Listen(10);
            //显示内容
            DisplayInfo("服务器端启动");
    
            //开启后台监听(监听客户端连接)
            Thread thClientCon = new Thread(ListionCilentCon);
            thClientCon.IsBackground = true;                    //后台线程
            thClientCon.Name = "thListionClientCon";
            thClientCon.Start();
        }
    
        /// <summary>
        /// 接听到客户端的连接
        /// </summary>
        private void ListionCilentCon()
        {
            Socket socMesgServer = null;                        //会话Socket
    
            try
            {
                while (IsListionContect)
                {
                    //等待接受客户端连接,此处会“阻断”当前线程
                    socMesgServer = socketServer.Accept();
                    //获取远程节点信息
                    string strClientIPAndPort = socketServer.RemoteEndPoint.ToString();
                    //把远程节点信息添加到DropDown控件中
                    Dropdown.OptionData op = new Dropdown.OptionData();
                    op.text = strClientIPAndPort;
                    Dro_IPList.options.Add(op);
                    //把会话Socket添加到集合中(为后面发送信息使用)
                    _DicSocket.Add(strClientIPAndPort, socMesgServer);
                    //控件显示,有客户端连接
                    DisplayInfo("有客户端连接");
    
                    //开启后台线程,接受客户端信息
                    Thread thClientMsg = new Thread(ReceivMsg);
                    thClientMsg.IsBackground = true;
                    thClientMsg.Name = "thListionClientMsg";
                    thClientMsg.Start(socMesgServer);
                }
            }
            catch (Exception)
            {
                IsListionContect = false;
                //关闭会话Socket
                if (socketServer != null)
                {
                    socketServer.Shutdown(SocketShutdown.Both);
                    socketServer.Close();
                }
                if (socMesgServer != null)
                {
                    socMesgServer.Shutdown(SocketShutdown.Both);
                    socMesgServer.Close();
                }
            }
        }
    
        /// <summary>
        /// 后台线程,接受客户端信息
        /// </summary>
        /// <param name="sockMsg"></param>
        private void ReceivMsg(object sockMsg)
        {
            Socket socketMsg = sockMsg as Socket;
    
            try
            {
                while (true)
                {
                    //准备接受数据缓存
                    byte[] msgAarry = new byte[1024 * 0124];
                    //准备接受客户端发来的套接字信息
                    int trueClientMsgLenth = socketMsg.Receive(msgAarry);
                    //byte数组转换为字符串
                    string strMsg = System.Text.Encoding.UTF8.GetString(msgAarry, 0, trueClientMsgLenth);
                    //显示接受的客户端消息内容
                    DisplayInfo("客户端消息:" + strMsg);
                }
            }
            catch (Exception)
            {
            }
            finally
            {
                DisplayInfo("有客户端断开连接了:" + socketMsg.RemoteEndPoint.ToString());
    
                //字典类断开连接的客户端消息
                _DicSocket.Remove(socketMsg.RemoteEndPoint.ToString());
                //客户端列表移除
                if (_DicDropdowm.ContainsKey(socketMsg.RemoteEndPoint.ToString()))
                {
                    Dro_IPList.options.Remove(_DicDropdowm[socketMsg.RemoteEndPoint.ToString()]);
                }
                //关闭Socket
                socketMsg.Shutdown(SocketShutdown.Both);
                socketMsg.Close();
            }
        
        }
    
        //向发送客户端会话
        public void SendMsg()
        { 
            //参数检查
            _CurClientIPValue = _CurClientIPValue.Trim();
            if (string.IsNullOrEmpty(_CurClientIPValue))
            {
                DisplayInfo("请选择要聊天的用户名称");
                return;
            }
    
            //判断是否与指定的Socket通信
            if (_DicSocket.ContainsKey(_CurClientIPValue))
            {
                //得到发送的消息
                string strSendMsg = InpSendMsg.text;
                strSendMsg = strSendMsg.Trim();
    
                if (!string.IsNullOrEmpty(strSendMsg))
                {
                    //信息转码
                    byte[] bySendArray = System.Text.Encoding.UTF8.GetBytes(strSendMsg);
                    //发送数据
                    _DicSocket[_CurClientIPValue].Send(bySendArray);
                    //记录发送数据
                    DisplayInfo("发送的数据:" + strSendMsg);
    
                    //控件重置
                    InpSendMsg.text = string.Empty;
                }
                else
                {
                    DisplayInfo("发送的消息不能为空!");
                }
            }
            else
            {
                DisplayInfo("请选择合法的聊天用户!");
            }
        
        }
    
        /// <summary>
        /// 主显示控件,显示消息
        /// </summary>
        /// <param name="str"></param>
        private void DisplayInfo(string str)
        {
            str = str.Trim();
            if (!string.IsNullOrEmpty(str))
            {
                _strDisplayInfo.Append(System.DateTime.Now.ToString());
                _strDisplayInfo.Append("  ");
                _strDisplayInfo.Append(str);
                _strDisplayInfo.Append("
    ");
                InpDisplayInfo.text = _strDisplayInfo.ToString();
            }
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    }

    客户端整体思路:

    1、初始化IP地址和端口号以及一些显示信息和套接字;

    2、启动客户端连接 _SockClient.Connect(endPoint);

    3、开启后台线程监听客户端发来的信息 _SockClient.Receive(byMsgArray);

    4、客户端发送数据到服务器  _SockClient.Send(byteArray);

    5、当然也应该包括退出系统和显示信息方法。

    /***
     * 
     * 
     * 
     *  客户端 
     * 
     * 
     */
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    using System;
    using System.Threading;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using UnityEngine.UI;
    
    public class Client : MonoBehaviour
    {
        public InputField InpIPAdress;                          //IP地址
        public InputField InpPort;                              //端口号
        public InputField InpDisplayInfo;                       //显示信息
        public InputField InpSendMsg;                           //发送信息
    
        private Socket _SockClient;                             //客户端Socket
        private IPEndPoint endPoint;
        private bool _IsSendDataConnection=true;                     //发送数据连接
        private StringBuilder _SbDisplayInfo = new StringBuilder();//控件追加信息
    
        // Start is called before the first frame update
        void Start()
        {
            InpIPAdress.text = "127.0.0.1";
            InpPort.text = "1000";
        }
    
        //客户端退出系统
        public void ExitSystem()
        { 
            //关闭客户端Socket
            if (_SockClient != null)
            {
                try
                {
                    //关闭连接
                    _SockClient.Shutdown(SocketShutdown.Both);
                }
                catch
                {
                }
                //清理资源
                _SockClient.Close();
            }
    
            //退出
            Application.Quit();
       
        }
    
        //启动客户端连接
        public void EnableClientCon()
        { 
            //通讯IP和端口号
            endPoint = new IPEndPoint(IPAddress.Parse(InpIPAdress.text), Convert.ToInt32(InpPort.text));
            //建立客户端Socket
            _SockClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
            try
            {
                //建立连接
                _SockClient.Connect(endPoint);
                //启动线程,监听服务端返回的消息
                Thread thrListenMsgFromServer = new Thread(ListionMsgFromServer);
                thrListenMsgFromServer.IsBackground = true;
                thrListenMsgFromServer.Name = "thrListenMsgFromServer";
                thrListenMsgFromServer.Start();
            }
            catch (Exception)
            {
                
                throw;
            }
            //控件显示连接服务端成功
            DisplayInfo("连接服务器成功!");
        
        }
    
        /// <summary>
        /// 后台线程监听服务端返回的消息
        /// </summary>
        public void ListionMsgFromServer()
        {
            try
            {
                while (true)
                {
                    //开辟消息内存区域
                    byte[] byMsgArray = new byte[1024 * 0124];
                    //客户端接受服务器返回的数据
                    int intTrueMsgLengh = _SockClient.Receive(byMsgArray);
                    //转化为字符串
                    string strMsg = System.Text.Encoding.UTF8.GetString(byMsgArray, 0, intTrueMsgLengh);
                    //显示收到的消息
                    DisplayInfo("服务器返回消息:" + strMsg);
                }
            }
            catch
            {
            }
            finally
            {
                DisplayInfo("服务器断开连接");
                _SockClient.Disconnect(true);
                _SockClient.Close();
            }
        
        }
    
        //客户端发送数据到服务器
        public void SendMsg()
        {
            string strSendMsg = InpSendMsg.text;
            if (!string.IsNullOrEmpty(strSendMsg))
            {
                //字节转化
                byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(strSendMsg);
                //发送
                _SockClient.Send(byteArray);
                //显示发送内容
                DisplayInfo("我:" + strSendMsg);
    
                //控件清空
                InpSendMsg.text = string.Empty;
            }
            else
            {
                DisplayInfo("提示:发送信息不能为空!");
            }
        }
    
        /// <summary>
        /// 主显示控件,显示消息
        /// </summary>
        /// <param name="str"></param>
        private void DisplayInfo(string str)
        {
            str = str.Trim();
            if (!string.IsNullOrEmpty(str))
            {
                _SbDisplayInfo.Append(System.DateTime.Now.ToString());
                _SbDisplayInfo.Append("  ");
                _SbDisplayInfo.Append(str);
                _SbDisplayInfo.Append("
    ");
                InpDisplayInfo.text = _SbDisplayInfo.ToString();
            }
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    }
  • 相关阅读:
    Android客户端消息推送原理简介
    优秀程序员的十个习惯
    能让你成为更优秀程序员的10个C语言资源
    成大事必备9种能力、9种手段、9种心态
    33个优秀的HTML5应用演示 (转)
    Maven学习:Eclipse使用maven构建web项目(转)
    使用fiddler模拟http get
    TLS握手
    风暴英雄 http 302重定向 正在等待游戏模式下载完成
    page template in kentico
  • 原文地址:https://www.cnblogs.com/Optimism/p/10535988.html
Copyright © 2011-2022 走看看