Unity实现服务器:1、Socket通信
最近研究了一下Unity的网络框架,踩了很多的坑,所以想在这里写篇文章作为总结,文章只针对实现,不讲过多的原理,后续会陆续更新完整的服务器框架。
要想实现服务器框架,首先就是要使用Socket进行通信,Socket通信大致逻辑:服务端暴露端口号和IP地址,客户端通过访问这个IP地址,进行数据传输,传输的数据为二进制数据。接下来为大家讲讲怎么实现。文章最后放出源码。
需要工具:unity、vs2019
1、首先在服务器端创建服务端脚本Server,我这直接用本地:
大致内容:暴露服务器ip地址、端口号、最大连接数,等待客户端连接后发送给客户端信息,接收客户端发来的信息。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
class Program
private static string _ipAdress = "127.0.0.1"; //ip地址
private static int _port = 5000; //端口号
private static int _maxConnect = 20; //最大连接数
private static Socket _serverSocket;
private static Socket _clientSocket;
static void Main(string[] args)
//1、创建一个服务端socket对象
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2、绑定一个ip和端口
IPAddress ipaddress = IPAddress.Parse(_ipAdress);//将一个字符串类型的ip地址,转换成一个IPAdress对象
EndPoint endPoint = new IPEndPoint(ipaddress, _port);
_serverSocket.Bind(endPoint);//向操作系统申请一个可用的ip和端口号来通讯
//3、开始监听客户端的连接请求
_serverSocket.Listen(_maxConnect);//设置最大连接数
Console.WriteLine(string.Format("开启服务端{0}...", _serverSocket.LocalEndPoint));
_clientSocket = _serverSocket.Accept();//阻塞当前线程,直到有一个客户端连接服务器
Console.WriteLine("接受到客户端的连接请求!");
//4、发送、接收消息
string message = "hello client";
byte[] data = Encoding.UTF8.GetBytes(message);//将字符串转成字节数组
_clientSocket.Send(data);
Console.WriteLine("服务器向客户端发送了一条消息:" + message);
//5、接收客户端发来的信息
byte[] data2 = new byte[1024];//存放消息的字节数容器 1M大小
int length = _clientSocket.Receive(data2);
string messgae2 = Encoding.UTF8.GetString(data2, 0, length);//bytes转换成string
Console.WriteLine("服务器接受到客户端发来的信息" + messgae2);
Console.ReadLine();
2、创建Unity项目,并添加Client脚本。
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
public class Client : MonoBehaviour
private Socket _tcpClient;
private string _serverIP = "127.0.0.1";//服务器ip地址
private int _serverPort = 5000;//端口号
void Start()
//1、创建socket
_tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2、建立一个连接请求
IPAddress iPAddress = IPAddress.Parse(_serverIP);
EndPoint endPoint = new IPEndPoint(iPAddress, _serverPort);
_tcpClient.Connect(endPoint);
Debug.Log("请求服务器连接");
//3、接受、发送消息
byte[] data = new byte[1024];
int length = _tcpClient.Receive(data);
var message = Encoding.UTF8.GetString(data, 0, length);
Debug.Log("客户端收到来自服务器发来的信息" + message);
//发送消息
string message2 = "Client Say To Hello";
_tcpClient.Send(Encoding.UTF8.GetBytes(message2));
Debug.Log("客户端向服务器发送消息" + message2);
}
3、开启服务器
4、开启客户端
将写好的脚本挂载在场景中
5、效果
最基本的通信已经实现,现在来开始重构一下代码。
服务器端:
将Client封装成一个类,要有初始化、开始接收、接收回调等方法
将Server封装成一个类,要有启动服务器,关闭服务器、接收信息等方法,并且还要有管理Client的方法。
客户端:
将Client封装成一个类,包括初始化、开始接收、接收回调等方法。
接下来实现:
服务器端:Server类
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
class Server
private Socket _serverSocket;
private int _prot;
private int _maxClient;
private string ipAdress;
public List<Client> ClientList = new List<Client>();//客户端列表
public Server(string ipAdress, int prot, int maxClient)
this.ipAdress = ipAdress;
this._prot = prot;
this._maxClient = maxClient;
Start();//启动
//启动服务器
public void Start()
//1、创建一个socket对象
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2、绑定一个ip和端口
IPAddress ipaddress = IPAddress.Parse(ipAdress);//将一个字符串类型的ip地址,转换成一个IPAdress对象
EndPoint endPoint = new IPEndPoint(ipaddress, _prot);
_serverSocket.Bind(endPoint);//向操作系统申请一个可用的ip和端口号来通讯
_serverSocket.Listen(_maxClient);//设置最大连接数
Console.WriteLine(string.Format("开启服务端{0}...", _serverSocket.LocalEndPoint));
StartAccept();
catch (Exception)//出现异常则关闭服务器
//Close();
throw;
//开始接收信息
private void StartAccept()
OnAccept();
//接收信息中
private void OnAccept()
while (true)
Socket clientSocket = _serverSocket.Accept();
Console.WriteLine(string.Format("客户端 {0} 连接", clientSocket.RemoteEndPoint));
Client client = new Client(clientSocket);
client.OnSend(Encoding.Default.GetBytes("登录成功"));
//关闭所有服务器
public void Close()
foreach (var client in ClientList)
client.Close();
_serverSocket.Close();
}
Client类:
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Server
class Client
private Thread _recvThread;
public Socket clientSocket;
public Client(Socket socket)
clientSocket = socket;
StartRecv();
//开始接收
private void StartRecv()
_recvThread = new Thread(OnRecv);
_recvThread.IsBackground = true;
_recvThread.Start();
//接收中
private void OnRecv()
while (true)
byte[] buff = new byte[1024];
clientSocket.Receive(buff);
Console.WriteLine(Encoding.Default.GetString(buff));
catch (Exception)
Close();
throw;
//发送信息
public void OnSend(byte[] data)
clientSocket.Send(data);
public void Close()
_recvThread.Abort();
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
Program:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
class Program
private static Server server;
private static void Start()
server = new Server("127.0.0.1", 5000, 20);
static void Main(string[] args)
Start();//开启服务器
客户端 SocketClient类:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class ClientSocket
private Socket _clientSocket;
private Thread _recvThread;
private string _rIP; //ip地址
private int _rProt; //端口
public ClientSocket(string _rIP, int _rProt)
this._rIP = _rIP;
this._rProt = _rProt;
Connect();
private void Connect()
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_clientSocket.Connect(new IPEndPoint(IPAddress.Parse(_rIP), _rProt));
OnSend(Encoding.Default.GetBytes("hello,server"));
StartRecv();
catch
throw;
//开始接收消息
private void StartRecv()
_recvThread = new Thread(OnRecv);
_recvThread.IsBackground = true;
Debug.Log("开始接收消息");
_recvThread.Start();
//接收中
private void OnRecv()
while (true)
byte[] buff = new byte[256];
_clientSocket.Receive(buff);
Debug.Log(Encoding.Default.GetString(buff));
//发送信息
public void OnSend(byte[] data)
_clientSocket.Send(data);
catch (Exception)
Close();
throw;
public void Close()
_recvThread.Abort();
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
调用:
using System.Net.Sockets;
using UnityEngine;
public class Client : MonoBehaviour
private readonly string _serverIP = "127.0.0.1";//服务器ip地址