当前位置: 首页 > news >正文

Unity中的简易TCP服务器/客户端

在本文中,我将向你介绍一个在Unity中实现的简单TCP服务器脚本,和一个简单的客户端脚本.

脚本 MyTcpServer 允许Unity应用创建一个TCP服务器,监听客户端的连接、异步处理客户端消息,并通过事件与Unity应用中的其他模块进行通信。

MyTcpServer 类是使用 C# 的 TcpListener 实现的自定义 TCP 服务器,该服务器监听指定端口的传入 TCP 连接,并以异步、非阻塞的方式处理与客户端的通信.

AcceptClientsAsync 方法是一个异步方法,使用 TcpListener.AcceptTcpClientAsync() 来接受客户端的连接。每当一个新客户端连接时,服务器会将其添加到 connectedClients 列表中,并为该客户端创建一个新的任务 (Task.Run()) 来处理客户端的消息。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using System.IO;
using System.Collections.Generic;public class MyTcpServer
{private static MyTcpServer instance;private TcpListener tcpListener;private CancellationTokenSource cts = new CancellationTokenSource();private List<TcpClient> connectedClients = new List<TcpClient>(); // 管理客户端连接public static bool isOnce = false;public static event Action<string> sendEvent;public static MyTcpServer Instance{get{if (instance == null){instance = new MyTcpServer();}return instance;}}public void StartServer(){try{var p = Path.Combine(Application.streamingAssetsPath, "MyPort.txt");if (!File.Exists(p)) return;var port = File.ReadAllText(p, Encoding.UTF8);Debug.Log($"Starting server on port {port}");tcpListener = new TcpListener(IPAddress.Any, int.Parse(port));tcpListener.Start();isOnce = true;Task.Run(() => AcceptClientsAsync(cts.Token));}catch (Exception ex){Debug.LogError($"Error starting server: {ex.Message}");}}private async Task AcceptClientsAsync(CancellationToken token){while (!token.IsCancellationRequested){try{TcpClient client = await tcpListener.AcceptTcpClientAsync();Debug.Log($"Client connected: {client.Client.RemoteEndPoint}");connectedClients.Add(client);_ = Task.Run(() => HandleClientAsync(client, token));}catch (Exception ex){Debug.LogError($"Error accepting client: {ex.Message}");}}}private async Task HandleClientAsync(TcpClient client, CancellationToken token){using (client){NetworkStream stream = client.GetStream();byte[] buffer = new byte[4096];while (!token.IsCancellationRequested){try{int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token);if (bytesRead == 0) break;string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);Debug.Log($"Received: {message}");sendEvent?.Invoke(message);}catch (Exception ex){Debug.LogError($"Error reading from client: {ex.Message}");break;}await Task.Delay(10, token);}}// Cleanup on client disconnectconnectedClients.Remove(client);}public void StopServer(){if (cts != null){cts.Cancel();if (tcpListener != null){tcpListener.Stop();tcpListener = null;}cts.Dispose();cts = null;}// Ensure that all connected clients are closed properlyforeach (var client in connectedClients){client.Close();}connectedClients.Clear();}
}

MyClient 类是一个简单的客户端实现,能够与 TCP 服务器进行通信。它提供了连接服务器、发送命令以及关闭连接等基本功能。

using System.Collections;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;public class MyClient
{private TcpClient client;private NetworkStream stream;private static MyClient _ins; // 单例实例private static bool connected = false;public static MyClient ins{get{if (_ins == null){_ins = new MyClient();}return _ins;}}// 私有构造函数,防止外部实例化private MyClient(){}public void Init(){if (!connected){connected = true;var path = Path.Combine(Application.streamingAssetsPath, "IpFile.txt");var p = Path.Combine(Application.streamingAssetsPath, "MyPort.txt");if (!File.Exists(p) || !File.Exists(path)) return;Debug.Log($"Reading IP configuration from: {path}");Debug.Log($"Reading port from: {p}");var ipAddress = File.ReadAllText(path, Encoding.UTF8);var port = File.ReadAllText(p, Encoding.UTF8);Debug.Log(ipAddress);Debug.Log(port);ConnectToServer(ipAddress, int.Parse(port));}}private async void ConnectToServer(string ip, int port){int maxRetryAttempts = 5; // 最大重试次数int retryDelayMilliseconds = 1500; // 重试间隔,单位为毫秒for (int attempt = 1; attempt <= maxRetryAttempts; attempt++){try{client = new TcpClient();await client.ConnectAsync(ip, port); // 异步连接服务器stream = client.GetStream();Debug.Log("Connected to server.");return; // 成功连接则退出方法}catch (SocketException e){Debug.LogError($"Attempt {attempt} failed to connect: {e.Message}");if (attempt < maxRetryAttempts){Debug.Log($"Retrying in {retryDelayMilliseconds / 1000} seconds...");await Task.Delay(retryDelayMilliseconds); // 等待重试}else{Debug.LogError("Max retry attempts reached. Unable to connect to server.");}}}}public async Task SendCommand(string command){if (stream != null && client.Connected){try{byte[] data = Encoding.UTF8.GetBytes(command);await stream.WriteAsync(data, 0, data.Length); // 发送数据到服务器Debug.Log($"Command sent: {command}");}catch (SocketException e){Debug.LogError($"Error sending command: {e.Message}");}}else{Debug.LogWarning("Not connected to server.");}}public void CloseConnection(){if (stream != null){stream.Close();stream = null;}if (client != null){client.Close();client = null;}Debug.Log("Connection closed.");}
}

相关文章:

Unity中的简易TCP服务器/客户端

在本文中&#xff0c;我将向你介绍一个在Unity中实现的简单TCP服务器脚本,和一个简单的客户端脚本. 脚本 MyTcpServer 允许Unity应用创建一个TCP服务器&#xff0c;监听客户端的连接、异步处理客户端消息&#xff0c;并通过事件与Unity应用中的其他模块进行通信。 MyTcpServe…...

Spring Boot 3.4 正式发布,结构化日志!

1 从 Spring Boot 3.3 升级到 3.4 1.1 RestClient 和 RestTemplate 新增对 RestClient 和 RestTemplate 自动配置的支持&#xff0c;可用 Reactor Netty 的 HttpClient 或 JDK 的 HttpClient。支持的客户端优先级&#xff1a; Apache HTTP Components (HttpComponentsClient…...

技术文档,they are my collection!

工作 今天这篇文章&#xff0c;献给一直撰写技术文档的自己。我自认为是公司中最爱写文档的人了&#xff0c;我们是一个不到40人的小公司&#xff0c;公司作风没有多么严谨&#xff0c;领导也不会要求我们写技术文档。但是从入职初至今&#xff0c;我一直保持着写技术文档…...

详解Qt之QtMath Qt数学类

文章目录 QtMath详解前言QtMath简介QtMath中的函数1. 三角函数1.1 qSin1.2 qCos 2. 指数与对数函数2.1 qExp2.2 qLn 3. 幂运算与平方根3.1 qPow3.2 qSqrt QtMath的优势1. 一致性与跨平台支持2. 与Qt生态系统集成3. 简洁性 总结 QtMath详解 前言 在C的开发中&#xff0c;数学运…...

人工智能与人类:共创未来的新篇章

数年前&#xff0c;当人工智能还停留在实验室的时候&#xff0c;很少有人能想到它会如此迅速地融入我们的日常生活。如今&#xff0c;从手机上的语音助手&#xff0c;到自动驾驶汽车&#xff0c;从智能家居到医疗诊断&#xff0c;AI的身影无处不在。这让我想起了20世纪初电力普…...

4.6 JMeter HTTP信息头管理器

欢迎大家订阅【软件测试】 专栏&#xff0c;开启你的软件测试学习之旅&#xff01; 文章目录 前言1 HTTP信息头管理器的位置2 常见的HTTP请求头3 添加 HTTP 信息头管理器4 应用场景 前言 在 JMeter 中&#xff0c;HTTP信息头管理器&#xff08;HTTP Header Manager&#xff09…...

非交换几何与黎曼ζ函数:数学中的一场革命性对话

非交换几何与黎曼ζ函数&#xff1a;数学中的一场革命性对话 非交换几何&#xff08;Noncommutative Geometry, NCG&#xff09;是数学的一个分支领域&#xff0c;它将经典的几何概念扩展到非交换代数的框架中。非交换代数是一种结合代数&#xff0c;其中乘积不是交换性的&…...

【设计模式】【行为型模式(Behavioral Patterns)】之观察者模式(Observer Pattern)

1. 设计模式原理说明 观察者模式&#xff08;Observer Pattern&#xff09; 是一种行为设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都会得到通知并自动更新。这种模式非常适合处理事件驱动系统&a…...

文件导入-使用java反射修改日期数据

文件导入时&#xff0c;时间类型通常不能直接导出&#xff0c;以下方法为批量处理类中日期类型转字符串类型。 Date/Datetime --> String(yyyy-mm-dd)Field[] declaredFields HrAviationstudentMonitorDTO.class.getDeclaredFields(); for (Field field : declaredFields) …...

【网络安全设备系列】10、安全审计系统

0x00 定义: 网络安全审计系统针对互联网行为提供有效的行为审计、内容审计、行为报警、行为控制及相关审计功能。从管理层面提供互联网的 有效监督&#xff0c;预防、制止数据泄密。满足用户对互联网行为审计备案及 安全保护措施的要求&#xff0c;提供完整的上网记录&#xf…...

Apache Maven Assembly 插件简介

Apache Maven Assembly 插件是一个强大的工具&#xff0c;允许您以多种格式&#xff08;如 ZIP、TAR 和 JAR&#xff09;创建项目的分发包。 该插件特别适用于将项目与其依赖项、配置文件和其他必要资源一起打包。 通过使用 Maven Assembly 插件&#xff0c;您可以将项目作为…...

ReentrantLock(可重入锁) Semaphore(信号量) CountDownLatch

目录 ReentrantLock(可重入锁) &Semaphore(信号量)&CountDownLatchReentrantLock(可重入锁)既然有了synchronized&#xff0c;为啥还要有ReentrantLock?Semaphore(信号量)如何确保线程安全呢&#xff1f;CountDownLatch ReentrantLock(可重入锁) &Semaphore(信号量…...

计算机网络习题解答--个人笔记(未完)

本篇文章为关于《计算机网络-自顶向下方法第七版》的阅读总结和课后习题解答(未完待续) 第二章&#xff1a; cookie&#xff1a;&#xff08;这里是比较老版本的HTTP&#xff0c;具体HTTPs是怎么实现的不是很清楚&#xff09;cookie的原理其实很简单。就是在HTTP消息头上又多…...

java虚拟机——频繁发生Full GC的原因有哪些?如何避免发生Full GC

什么是Full GC Full GC&#xff08;Full Garbage Collection&#xff09;是Java垃圾收集过程中的一种形式&#xff0c;它涉及整个堆内存&#xff08;包括年轻代和老年代&#xff09;以及方法区的垃圾收集。Full GC是一个相对重量级的操作&#xff0c;因为它需要遍历和回收整个…...

python学习笔记(12)算法(5)迭代与递归

一、迭代 迭代&#xff08;iteration&#xff09;是一种重复执行某个任务的控制结构。在迭代中&#xff0c;程序会在满足一定的条件下重复执行某段代码&#xff0c;直到这个条件不再满足。 迭代通常用于解决需要逐步推进的计算问题&#xff0c;例如遍历数组、计算阶乘等。迭代…...

从零开始:Linux 环境下的 C/C++ 编译教程

个人主页&#xff1a;chian-ocean 文章专栏 前言&#xff1a; GCC&#xff08;GNU Compiler Collection&#xff09;是一个功能强大的编译器集合&#xff0c;支持多种语言&#xff0c;包括 C 和 C。其中 gcc 用于 C 语言编译&#xff0c;g 专用于 C 编译。 Linux GCC or G的安…...

Rust学习(十):计算机科学简述

Rust学习&#xff08;十&#xff09;&#xff1a;计算机科学简述 在计算机技术这片广袤的领域中&#xff0c;深入理解其内在机制与逻辑需要付出诸多努力。 学习基础知识是构建计算机技术能力大厦的基石&#xff0c;而这一过程往往漫长而艰辛。只有在对基础知识有了扎实的掌握…...

【西瓜书】剪枝与样本值处理——预剪枝、后剪枝、连续值、缺失值

目录 预剪枝 后剪枝 处理连续值 处理缺失值 剪枝&#xff08;pruning&#xff09;是决策树学习算法对付“过拟合”的主要手段。 在决策树学习过程中&#xff0c;有时会造成决策树分枝过多&#xff0c;就可能造成过拟合&#xff0c;可通过主动去掉一些分支来降低过离合的风…...

NLP 1、人工智能与NLP简介

人人都不看好你&#xff0c;可偏偏你最争气 —— 24.11.26 一、AI和NLP的基本介绍 1.人工智能发展流程 弱人工智能 ——> 强人工智能 ——> 超人工智能 ① 弱人工智能 人工智能算法只能在限定领域解决特定的问题 eg&#xff1a;特定场景下的文本分类、垂直领域下的对…...

常见线程安全问题之Double Checked Locking

创作内容丰富的干货文章很费心力&#xff0c;感谢点过此文章的读者&#xff0c;点一个关注鼓励一下作者&#xff0c;激励他分享更多的精彩好文&#xff0c;谢谢大家&#xff01; 双重锁定检查&#xff08;Double Checked Locking&#xff0c;下称 DCL&#xff09;是并发下实现懒…...

Redis(非关系型数据库)的作用 详细解读

edis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的、基于内存的数据结构存储系统。它具有极高的读写性能&#xff0c;并且能够支持多种数据结构的存储。Redis 最初的设计目标是作为一个缓存解决方案&#xff0c;但随着其功能的不断扩展&#xff0c;…...

互联网视频推拉流EasyDSS视频直播点播平台视频转码有哪些技术特点和应用?

视频转码本质上是一个先解码再编码的过程。在转码过程中&#xff0c;原始视频码流首先被解码成原始图像数据&#xff0c;然后再根据目标编码标准、分辨率、帧率、码率等参数重新进行编码。这样&#xff0c;转换前后的码流可能遵循相同的视频编码标准&#xff0c;也可能不遵循。…...

python之多元线性回归

目录 前言实战 前言 多元线性回归是回归分析中的一种复杂模型&#xff0c;它考虑了多个输入变量对输出变量的影响。与一元线性回归不同&#xff0c;多元线性回归通过引入多个因素&#xff0c;更全面地建模了系统关系。 多元线性回归模型的表达式为&#xff1a; f ( X ) K T …...

学习threejs,使用设置lightMap光照贴图创建阴影效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshLambertMaterial…...

一,SQL注入解题(猫舍)

封神台 第一章&#xff1a;为了女神小芳&#xff01; Tips: 通过sql注入拿到管理员密码&#xff01; 尤里正在追女神小芳&#xff0c;在得知小芳开了一家公司后&#xff0c;尤里通过whois查询发现了小芳公司网站 学过一点黑客技术的他&#xff0c;想在女神面前炫炫技。于是他…...

海康大华宇视视频平台EasyCVR私有化部署视频平台海康ISUP是什么?如何接入到EasyCVR?

在现代安防领域&#xff0c;随着技术的发展和需求的增加&#xff0c;对于视频监控系统的远程管理和互联互通能力提出了更高的要求。海康威视的ISUP协议&#xff08;以及功能相似的EHOME协议&#xff09;因此应运而生&#xff0c;它们为不具备固定IP接入的设备提供了一种有效的中…...

Java ArrayList 与顺序表:在编程海洋中把握数据结构的关键之锚

我的个人主页 我的专栏&#xff1a;Java-数据结构&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 前言&#xff1a;在 Java编程的广袤世界里&#xff0c;数据结构犹如精巧的建筑蓝图&#xff0c;决定着程序在数据处理与存储时的效率、灵活性以…...

windows下安装wsl的ubuntu,同时配置深度学习环境

写在前面&#xff0c;本次文章只是个人学习记录&#xff0c;不具备教程的作用。个别信息是网上的&#xff0c;我会标注&#xff0c;个人是gpt生成的 安装wsl 直接看这个就行&#xff1b;可以不用备份软件源。 https://blog.csdn.net/weixin_44301630/article/details/1223900…...

开展网络安全成熟度评估:业务分析师的工具和技术

想象一下,您坐在飞机驾驶舱内。起飞前,您需要确保所有系统(从发动机到导航工具)均正常运行。现在,将您的业务视为飞机,将网络安全视为飞行前必须检查的系统。就像飞行员依赖检查表一样,业务分析师使用网络安全成熟度评估来评估组织对网络威胁的准备程度。这些评估可帮助…...

Maven Surefire 插件简介

Maven Surefire 插件是 Maven 构建系统中的一个关键组件&#xff0c;专门用于在构建生命周期中执行单元测试。 它通常与 Maven 构建生命周期的测试阶段绑定&#xff0c;确保所有单元测试在项目编译后和打包前被执行。 最新版本 Maven Surefire 插件的最新版本为 3.5.2。 使…...

注册公司网站怎么收费/企业网站建设报价

计数排序的基本思想是&#xff1a;统计一个数序列中小于某个元素a的个数为n,则直接把该元素a放到第n1个位置上。当然当过有几个元素相同时要做适当的调整&#xff0c;因为不能把所有的元素放到同一个位置上。计数排序假设输入的元素都是0到k之间的整数。// 8-2.计数排序.cpp : …...

注册网站怎么注销/营销方法有哪些方式

本人已经疯了...快写完了而关掉浏览器丢失数据之事在此文章上发生了两次,所以本人倍加珍惜这节讲 一下Asp.netMVC中的Helper何谓Helper,其实就是在View中为了实现一些灵活功能而写的方法组其实Asp.net MVC的View是Aspx的页面,本身可以声明定义方法,那为什么要有Helper呢其实无非…...

小程序制作公司/seo排名快速优化

1. 双向链表 1.1 概念 双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c;从双向链表中的任意一个结点开始&#xff0c;都可以很方便地访问它的前驱结点和后继结点。 1.2 实例…...

迅当网络深圳外贸网站建设/个人网页模板

KVM是Kernel Based Virtual Machine的简称&#xff0c;能够利用硬件虚拟扩展来提供多种操作系统的虚拟化软件&#xff0c;KVM能够通过两种方式来管理&#xff0c;一种是命令行&#xff0c;另一种是图形化界面。 Virt-Manager(Virtual Machine Manager)是基于KVM使用最为频繁的管…...

wordpress 5.2/有哪些营销推广方式

功能 支持文件上传功能支持文件下载功能支持断点续传功能支持连续多个文件的上传下载 文件上传下载流程 在确认断点的时候会利用md5进行数据校验&#xff0c;防止数据发生更改。 服务端 采用多线程的Reactor模式。即一个线程对应多个filesocket进行文件上传下载。线程个数…...

做平面免费接单网站/品牌网络营销案例

map:数据的插入 在构造map容器后&#xff0c;我们就可以往里面插入数据了。这里讲三种插入数据的方法&#xff1a;第一种&#xff1a;用insert函数插入pair数据map<int, string> mapStudent;mapStudent.insert(pair<int, string>(1,“student_one”)); 第二种&…...