1 前言

​ 在多人对战网络游戏中,玩家之间一般不是直接通讯,而是与服务器通讯,服务器再把消息转发给其他玩家。网络通讯一般基于 Socket 实现,也有一些开源网络游戏框架,如:光子引擎 Photon,其底层仍然使用 Socket 实现网络通讯。

​ 同步 Socket 是指 Socket 的部分方法会阻塞当前线程(如:Accept、Receive 方法),直到方法返回,当前线程才会继续执行。

​ 当有客户连接上服务器后,服务器会生成一个 Socket(通过 Accept 方法返回 Socket,可以理解为客服),与客户对接,进行信息交流。

2 案例

​ 1)Socket 基本操作接口

​ BaseSocket.cs

public interface BaseSocket {
void Listening(); // 监听连接, 监听消息
void Receive(); // 接收到消息
void Send(string msg); // 发送消息
}

​ 2)服务端

​ SyncSocketServer.cs

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading; public class SyncSocketServer : BaseSocket{
private Socket serverSocket; // 服务端通讯主机socket, 监听打进来的电话,并转接给客服
private Socket kefuScoket; // 客服socket, 负责与客户一对一通讯
private Action<string> msgCallback; // 消息回调
private byte[] readBuff; // 收到消息的缓存 public SyncSocketServer(Action<string> callback) {
msgCallback = callback;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 12345);
serverSocket.Bind(endPoint); // 绑定ip和端口
new Thread(() => {
Listening();
}).Start();
} public void Listening() {
serverSocket.Listen(1); // 监听电话连接, 设置最大客服人数, 如果是0就是无限个客服
kefuScoket = serverSocket.Accept(); // 接电话, 分配客服和客户进行一对一通信, 没有电话打进来就会一直阻塞
msgCallback("客服的本地端口是: " + kefuScoket.LocalEndPoint.ToString());
msgCallback("客户的远程端口是: " + kefuScoket.RemoteEndPoint.ToString());
readBuff = new byte[1024];
while(true) {
Receive();
}
} public void Receive() {
Array.Clear(readBuff, 0, readBuff.Length); // 清空缓存
int count = kefuScoket.Receive(readBuff); // 收到消息, 并存放在缓冲区, 没有消息就会一直阻塞
string msg = Encoding.UTF8.GetString(readBuff, 0, count);
msgCallback("客户端发来消息: " + msg);
} public void Send(string msg) {
byte[] buffer = Encoding.UTF8.GetBytes(msg);
kefuScoket.Send(buffer);
} ~SyncSocketServer() {
kefuScoket.Close();
serverSocket.Close();
}
}

​ 3)客户端

​ SyncSocketClient.cs

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading; public class SyncSocketClient : BaseSocket {
private Socket clientSocket; // 客户端socket
private Action<string> msgCallback; // 消息回调
private byte[] readBuff; // 收到消息的缓存 public SyncSocketClient(Action<string> callback) {
msgCallback = callback;
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
new Thread(() => {
clientSocket.Connect("127.0.0.1", 12345); //连接服务器, 未连接上就会一直阻塞
Listening();
}).Start();
} public void Listening() {
readBuff = new byte[1024];
while(true) {
Receive();
}
} public void Receive() {
Array.Clear(readBuff, 0, readBuff.Length); // 清空缓存
int count = clientSocket.Receive(readBuff); // 收到消息, 并存放在缓冲区, 没有消息就会一直阻塞
string msg = Encoding.UTF8.GetString(readBuff, 0, count);
msgCallback("客服发来消息: " + msg);
} public void Send(string msg) {
byte[] buffer = Encoding.UTF8.GetBytes(msg);
clientSocket.Send(buffer);
} ~SyncSocketClient() {
clientSocket.Close();
}
}

​ 4)测试类

​ SyncSocketTest.cs

using UnityEngine;

public class SyncSocketTest : MonoBehaviour {
private BaseSocket socket; // 客户端/服务端socket
private string sendText; // 发送的消息
private string receiveText; // 接收的消息
private bool isSideInited = false; // 是否已初始化端测
private string sideTag = null; // 端测标记, 服务端/客户端 private void Awake() {
Application.runInBackground = true; // 支持后台运行
} private void OnGUI() {
InitSide();
initSideView();
} private void InitSide() { // 初始化端测
if (!isSideInited) {
CreateServer();
CreateClient();
}
} private void CreateServer() { // 创建服务器
if (GUILayout.Button("创建服务器")) {
socket = new SyncSocketServer((msg) => {
receiveText += msg + "\n";
});
sideTag = "服务端";
isSideInited = true;
}
} private void CreateClient() { // 创建客户端
if (GUILayout.Button("创建客户端")) {
socket = new SyncSocketClient((msg) => {
receiveText += msg + "\n";
});
sideTag = "客户端";
isSideInited = true;
}
} private void initSideView() { // 初始化端测界面
if (isSideInited) {
GUILayout.Label(sideTag);
sendText = GUILayout.TextField(sendText);
if (GUILayout.Button("发送")) {
socket.Send(sendText);
}
GUILayout.Label("接收到的消息: ");
GUILayout.Label(receiveText);
}
}
}

​ 5)运行效果

​ 声明:本文转自【Unity3D】同步Socket通讯

【Unity3D】同步Socket通讯的更多相关文章

  1. Unity3d基于Socket通讯例子(转)

    按语:按照下文,服务端利用网络测试工具,把下面客户端代码放到U3D中摄像机上,运行结果正确. http://www.manew.com/thread-102109-1-1.html 在一个网站上看到有 ...

  2. GJM: Unity3D基于Socket通讯例子 [转载]

    首先创建一个C# 控制台应用程序, 直接服务器端代码丢进去,然后再到Unity 里面建立一个工程,把客户端代码挂到相机上,运行服务端,再运行客户端. 高手勿喷!~! 完全源码已经奉上,大家开始研究吧! ...

  3. Unity3d网络游戏Socket通讯

    http://blog.csdn.net/wu5101608/article/details/37999409

  4. 利用BlazeDS的AMF3数据封装与Flash 进行Socket通讯

    前几天看到了Adobe有个开源项目BlazeDS,里面提供了Java封装AMF3格式的方法.这个项目貌似主要是利用Flex来Remoting的,不过我们可以利用他来与Flash中的Socket通讯. ...

  5. c#Socket通讯

    参考http://bbs.cskin.net/thread-326-1-1.html的大神的代码 socket封装 /// <summary> /// 自定义Socket对象 /// &l ...

  6. 闲来无事,写个基于TCP协议的Socket通讯Demo

    .Net Socket通讯可以使用Socket类,也可以使用 TcpClient. TcpListener 和 UdpClient类.我这里使用的是Socket类,Tcp协议. 程序很简单,一个命令行 ...

  7. 试解析Tomcat运行原理(一)--- socket通讯

    关于这篇文章也确实筹划了很久,今天决定开篇写第一篇,说起tomcat首先很容易联想到IIS,因为我最开始使用的就是.net技术,我第一次使用asp写学生成绩管理系统后,很茫然如何让别人都能看到或者说使 ...

  8. c# TCP Socket通讯基础

    在做网络通讯方面的程序时,必不可少的是Socket通讯. 那么我们需要有一套既定的,简易的通讯流程. 如下: <pre name="code" class="csh ...

  9. Android笔记:Socket通讯常见问题

    经验证的socket通讯问题 1.如果是模拟器和本机PC直接通讯,需要使用本机IP地址 而不是 10.0.2.2  如本机的静态地址为192.168.1.2 则直接使用该地址 2.接收和连接代码不能在 ...

  10. java socket通讯(二)处理多个客户端连接

    通过java socket通讯(一) 入门示例,就可以实现服务端和客户端的socket通讯,但是上一个例子只能实现一个服务端和一个客户端之间的通讯,如果有多个客户端连接服务端,则需要通过多线程技术来实 ...

随机推荐

  1. 使用QQ屏幕识图实现识别表格功能

    1.问题 目前市场上的OCR工具对于识别表格功能均是采取了收费制度,但我们时常要进行一些表格的复制(原表格为图片) 便可以使用QQ或钉钉自带的功能来实现 2.解决 1.QQ屏幕识图 先使用屏幕识图功能 ...

  2. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.11.22)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...

  3. 【面试题精讲】说一说springboot加载配置文件优先级

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 文章更新计划 系列文章地址 Spring Boot 加载配置文 ...

  4. Python学习之十二_tkinter的学习与使用

    Python学习之十二_tkinter的学习与使用 摘要 本来想说会用QT5进行界面编程 但是发现比较繁琐 还是先学习使用 tkinter的方式进行界面化的编写和学习了 基础知识 tkinter是一个 ...

  5. [转帖]绕过CDN查看网站真实IP

    https://www.itblogcn.com/article/viewcdnip.html   这是一个总结帖,查了一下关于这个问题的国内外大大小小的网站,对其中说的一些方法总结归纳形成. 首先, ...

  6. [转帖]GPT4All 一个开源 ChatGPT

    https://zhuanlan.zhihu.com/p/618947904 通用预训练语言模型. ChatGPT 正在迅速发展与传播,新的大型语言模型 (LLM) 正在以越来越快的速度开发.就在过去 ...

  7. [转帖]iozone - 性能压力测试工具

    <存储工具系列文章>主要介绍存储相关的测试和调试工具,包括不限于dd.fio.vdbench.iozone.iometer.cosbench等性能负载工具,及strace等调试工具. 1 ...

  8. [转帖]Linux系统:page fault

    Linux进程如何访问内存 Linux下,进程并不是直接访问物理内存,而是通过内存管理单元(MMU)来访问内存资源,原因后面会讲到. 为什么需要虚拟内存地址空间 假设某个进程需要4MB的空间,内存假设 ...

  9. [转帖]dd命令中dsync和fsync区别

    在Linux系统中经常会使用dd命令来测试硬盘的写入速度,命令会涉及几个常用参数:sync.dsync.fsync与fdatasync # dd if=/dev/zero of=/tmp/1G bs= ...

  10. K8S的pod展示镜像信息

    https://kubernetes.io/zh/docs/tasks/access-application-cluster/list-all-running-container-images/ ku ...