Unity使用C#实现简单Scoket连接及服务端与客户端通讯

2023-11-15

简介:

网络编程是个很有意思的事情,偶然翻出来很久之前刚开始看Socket的时候写的一个实例,贴出来吧

Unity中实现简单的Socket连接,c#中提供了丰富的API,直接上代码。

服务端代码:

    Thread connectThread;//当前服务端监听子线程
    public string address;//当前地址
    public int port;//当前本地端口
    TcpClient romoteClient;//远程客户端

    // Use this for initialization
    void Start()
    {
        connectThread = new Thread(InitServerSocket);
        connectThread.Start();
    }

    /// <summary>
    /// 实例化服务端Socket
    /// </summary>
    public void InitServerSocket()
    {
        int bufferSize = 8192;//缓冲区大小
        IPAddress ip = IPAddress.Parse(address);
        //新建TCP连接,并开启监听子线程
        TcpListener tcpListener = new TcpListener(ip, port);
        tcpListener.Start();
        Debug.Log("服务端-->客户端完成,开启tcp连接监听");
        //如果有远程客户端连接,此时得到其对象用于通讯
        romoteClient = tcpListener.AcceptTcpClient();
        Debug.Log("客户端连接开始 本地地址端口: " + romoteClient.Client.LocalEndPoint + "  远程客户端地址端口: " + romoteClient.Client.RemoteEndPoint);
        NetworkStream stream = romoteClient.GetStream();
        do
        {
            try
            {
                //获取与客户端连接数据
                byte[] buffer = new byte[bufferSize];
                int byteRead = stream.Read(buffer, 0, bufferSize);
                if (byteRead == 0)
                {
                    Debug.Log("客户端断开");
                    break;
                }
                string msg = Encoding.UTF8.GetString(buffer, 0, byteRead);
                Debug.Log("接收到客户端的数据: " + msg + "   数据长度: " + byteRead + "字节");

            }
            catch (Exception ex)
            {
                Debug.Log("客户端异常: " + ex.Message);
                //客户端出现异常或者断开的时候,关闭线程防止溢出
                tcpListener.Stop();
                break;
            }
        } while (true);
    }

    /// <summary>
    /// 服务器端根据当前连接的远程客户端发送消息
    /// </summary>
    public void SendMessageToClient()
    {
        if (romoteClient != null)
        {
            romoteClient.Client.Send(Encoding.UTF8.GetBytes("Hello Client ,This is Server!"));
        }
    }

    /// <summary>
    /// 销毁时关闭监听线程及连接
    /// </summary>
    void OnDestroy()
    {
        if (romoteClient != null)
            romoteClient.Close();
        if (connectThread != null)
            connectThread.Abort();
    }

客户端代码:

    public string serverAddress;//服务器地址
    public int port;//服务器端口
    private TcpClient localClient;//当前tcp客户端
    private Thread receiveThread;//接收服务器消息线程
    private byte[] resultBuffer = new byte[1024];//服务器返回流字节
    private string resultStr;//服务器返回字符串

    void Start()
    {
        //连接至服务端
        InitClientSocket();
    }

    /// <summary>
    /// 销毁时操作
    /// </summary>
    private void OnDestroy()
    {
        if (localClient != null)
            localClient.Close();
        if (receiveThread != null)
            receiveThread.Abort();
    }

    /// <summary>
    /// 客户端实例化Socket连接
    /// </summary>
    private void InitClientSocket()
    {
        localClient = new TcpClient();
        try
        {
            //当前客户端连接的服务器地址与远程端口
            localClient.Connect(IPAddress.Parse(serverAddress), port);
            //开始接收服务器消息子线程
            receiveThread = new Thread(SocketReceiver);
            receiveThread.Start();
            Debug.Log("客户端-->服务端完成,开启接收消息线程");
        }
        catch (Exception ex)
        {
            Debug.Log("客户端连接服务器异常: " + ex.Message);
        }
        Debug.Log("连接到服务器 本地地址端口:" + localClient.Client.LocalEndPoint + "  远程服务器端口:" + localClient.Client.RemoteEndPoint);
    }

    /// <summary>
    /// 客户端发送消息到服务器
    /// </summary>
    private void SendMessageToServer()
    {
        try
        {
            string clientStr = "Hello Server, This is Client!";
            //获取当前客户端的流对象,然后将要发送的字符串转化为byte[]写入发送
            NetworkStream stream = localClient.GetStream();
            byte[] buffer = Encoding.UTF8.GetBytes(clientStr);
            stream.Write(buffer, 0, buffer.Length);
        }
        catch (Exception ex)
        {
            Debug.Log("发送消息时服务器产生异常: " + ex.Message);
        }
    }

    /// <summary>
    /// 客户端检测收到服务器信息子线程
    /// </summary>
    private void SocketReceiver()
    {
        if (localClient != null)
        {
            while (true)
            {
                if (localClient.Client.Connected == false)
                    break;
                //在循环中,
                localClient.Client.Receive(resultBuffer);
                resultStr = Encoding.UTF8.GetString(resultBuffer);
                Debug.Log("客户端收到服务器消息 : " + resultStr);
            }
        }
    }

此时,面板填入服务端的地址及端口,运行服务端,再运行客户端,客户端点击发送消息,服务器收到消息,服务端发送消息后,客户端收到消息。本人是在两台机器上进行测试,Debug如下:

服务端:


客户端:



注意事项:

1.服务端和客户端的地址不要写错

2.服务端的端口确保未被占用

3.在进行通讯的时候,要保持字符串编码格式一致

4.子线程的生命周期,记得销毁,为了保证在主线程销毁同时销毁子线程可以使用thread.IsBackground = true

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity使用C#实现简单Scoket连接及服务端与客户端通讯 的相关文章

随机推荐

  • webpack之引入css

    前言 本文演示了如何打包css文件 涉及到的loader css loader style loader css loader的任务 把css文件作为模块打包 style loader的任务 把打包好的css文件动态的插入到html文件的
  • js中获取token的函数

    1 从cookies获取 从Cookies中获取token function getToken var strcookie document cookie 获取cookie字符串 var arrcookie strcookie split
  • 功能安全专题之功能安全概念阶段

    目录 前言 1 基本概念 1 1 相关项定义 Item Definition 1 2 相关项的构成 1 3 危害分析与风险识别 Hazard Analysis Risk Assessment 1 4 危害与危害事件 Hazard and H
  • Mysql进阶四:常见函数-流程控制函数

    进阶四 流程控制函数 作者 alicomon 寄语读者 博客为学习记录 目的有二 记录知识点 方便温故知新 为读者提供帮助 用于交流 共同提高 流程控制函数 可好玩了 1 if函数 if else 函数 SELECT IF 10 gt 5
  • k8s之三、pod 生命周期/ 探针/ 调度策略/ 副本ReplicaSet / 控制器Deployment

    pod 生命周期官方文档 https kubernetes io zh cn docs concepts workloads pods pod lifecycle 一 容器初始化 创建当前pod容器前 先创建 依赖的其他 container
  • python打包后打开闪退问题解决方法总结

    最近写了一个python项目 今天打包后却发现没有反应 查了一些资料说在程序最后加一个input输入语句可以停留在这里 查看看到报错原因 我加了input语句之后执行下面指令进行打包 pyinstaller F hidden import
  • 整型有哪几种形式?各种形式有什么区别?

    整型有哪几种形式 C 中提供的整数类型有三种 int long short 每种类型又分为有符号和无符号两种类型 有符号整数既可以表示非负整数 又可以表示负整数 但是 无符号整数不能表示负数 只能表示非负整数 一 无符号整数 在内存中 in
  • 素数环

    昨天晚上 突然想读刘汝佳老师书中的例题 素数环 但是突然自己就有了思路 于是便自己实现了一下 但是 由于昨晚时间比较晚 程序是写完了 但是没调试出来 今天一大早就开始调试 花了半小时终于调试出来了 好开心 中心思想是 回溯 上代码 incl
  • sqli-labs布尔盲注和时间盲注相结合的脚本实现

    import time import requests 定义一个变量 用于存放cookie值 HEADER cookie Idea 69a0360c 059291e0 9967 4fe4 bb5e 2524cdcf69d4 security
  • 多元共进|探索社区故事,助力开发者成长

    技术社区中的多元交流 带来丰富的灵感思维 为开发者的发展成长注入不竭的动力 谷歌凭借多种开发者生态项目和社区活动 辅助开发者在学习和成长的道路上稳步前行 中国的开发市场目前正处于全球视野中的重要位置 与各地的开发者交流互动也成为了中国开发者
  • 利用leapmotion实现抓取一个立方体

    1 基础设置 2 拖进来LeapHandController 显示为蓝色 其中 Edit Time Pose选择的是不同的模式 是桌面模式还是VR模式 3 拖进来HandModels 此部分为手势模型 为新建空物体 然后加上Hand Mod
  • 关于visual studio中的$(ConfigurationName)疑问

    关于visual studio中的 ConfigurationName 疑问 2012 12 02 16 09 15 转载 标签 it 分类 程序员之路 关于vs中的各种路径的值de查看方法 来源 http social msdn micr
  • Python---三大流程控制

    三大流程控制语句 1 顺序 按顺序去执行步骤 是最基本的代码执行规则 不做过多的解释 2 分支 单分支 if 条件 满足条件做什么 双分支 if 条件 满足条件做什么 else 不满足条件做什么 三元运算符 双份支的简化版 result 满
  • 关于scanf和printf的一些问题&&EOF和~的问题

    1 scanf和printf的返回值 在C语言中 scanf和printf这两个函数是标准输入输出库中的函数 它们在使用时不返回具体的值 而是通过输入输出参数来完成相应的功能 scanf函数 scanf函数用于从标准输入读取数据并根据提供的
  • KNN 原理及参数总结

    文章目录 前言 1 KNN 原理 2 KNN 优缺点 3 KNN 算法三要素 4 KNN 算法实现 5 sklearn实现KNN算法 前言 针对一个完整的机器学习框架目前还没有总结出来 所以目前只能总结每一个单独的算法 由于现在研究的重点是
  • 详解虚短、虚断以及在运算放大器中的应用

    详解虚短 虚断以及在运算放大器中的应用 一 运算放大器 运算放大器 后续简称运放 是一种集成电路 内部有很多三极管类晶体管的组合 外围接很少的电子元器件就能够实现放大信号的作用 并且信号干净 漂亮 1 1 开环 闭环 运算放大器电路 开环电
  • 2021年新版-编程基础训练32题-附提示和答案

    2021年新版 编程基础训练32题 附提示和答案 1 用级数法求圆周率 题目 圆周率十分重要 不仅仅是在数学理论上 即便在千年前的古代 工程上的需求 也迫切需要我们知道圆周率的尽量精确的数值 求圆周率 有很多种方法 级数法就是简便易行的方法
  • 牛客网Python篇入门编程习题

    目 录 一 输入输出 二 类型转换 三 字符类型 四 列表类型 五 运算符号 六 条件语句 七 循环语句 八 元组类型 九 字典类型 十 内置函数 十一 面向对象 十二 正则表达 本文题库非常适合刚刚接触Python编程的同学 有兴趣的同学
  • STlink V2 烧录器使用教学 【STM32篇】

    STlink V2 是一款支持STM32 STM8 烧录的常规工具 本帖主要讲解STM32 的烧录过程 STM32有2种烧录接口 分别为古老的Jtag接口和目前最常规的SWD接口 由于SWD只需要4条线就能烧录 目前STM32硬件工程师用S
  • Unity使用C#实现简单Scoket连接及服务端与客户端通讯

    简介 网络编程是个很有意思的事情 偶然翻出来很久之前刚开始看Socket的时候写的一个实例 贴出来吧 Unity中实现简单的Socket连接 c 中提供了丰富的API 直接上代码 服务端代码 Thread connectThread 当前服