Unity 搭建简易TCP服务器
前言
调试ESP8266的时候需要一个服务器,Unity用着比较顺手,就搭建了一个简易的服务器。
运行截图
使用Socket测试工具测试完成
描述
创建服务器基本变量
创建要使用的基本变量
/// <summary>
/// 服务器IP
/// </summary>
public string serverIP = "0.0.0.0";
/// <summary>
/// 服务器端口
/// </summary>
public int serverPoint = 8080;
/// <summary>
/// 负责监听消息的Socket
/// </summary>
Socket listenSocket;
/// <summary>
/// 所有客户端Socket
/// </summary>
List<Socket> clientSockets=new List<Socket>();
/// <summary>
/// 字节流数据
/// </summary>
private byte[] buffer = new byte[1024 * 1024 * 2];
开启服务器并开始监听客户端连接
/// <summary>
/// 开启服务器,并开始监听客户端连接
/// </summary>
public void StartServer()
{
//新建一个负责监听的Socket
listenSocket= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP地址和端口
IPAddress ip = IPAddress.Parse(serverIP);
IPEndPoint point = new IPEndPoint(ip,serverPoint);
//绑定监听端口
listenSocket.Bind(point);
//设置监听队列
listenSocket.Listen(10);
//开始监听客户端连接并设置连接回调
listenSocket.BeginAccept(BeginAcceptCallBack, listenSocket);
Debug.Log("服务器开启成功");
}
处理客户端连接回调
/// <summary>
/// 客户端连接回调
/// </summary>
/// <param name="ar"></param>
private void BeginAcceptCallBack(IAsyncResult ar)
{
//客户端连接成功,新建一个客户端的Socket
Socket clientSocket = listenSocket.EndAccept(ar);
Debug.Log("客户端连接成功 " + clientSocket.RemoteEndPoint.ToString());
//将所有连接的客户端socket都放到列表中
clientSockets.Add(clientSocket);
//给刚才连接的客户端发送Hello
clientSocket.Send(Encoding.UTF8.GetBytes("Hello"));
//开始监听这个客户端发了什么消息,并且设置回调
clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, BeginReceiveCallback, clientSocket);
//继续监听其他客户端连接
listenSocket.BeginAccept(BeginAcceptCallBack, listenSocket);
}
接收客户端消息
/// <summary>
/// 收到客户端消息回调
/// </summary>
/// <param name="ar"></param>
private void BeginReceiveCallback(IAsyncResult ar)
{
//拿到当前这个客户端的Socket
Socket client = (Socket)ar.AsyncState;
client.EndReceive(ar);
string msg = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Debug.Log("服务器收到客户端 " + client.RemoteEndPoint + " 消息:"+msg);
//如果消息是空的,说明客户端主动断开连接,就要把这个客户端Socket给干掉 Poll 方法将会检查 Socket 的状态
if (client.Poll(-1, SelectMode.SelectRead) && client.Available == 0)
{
Debug.Log("客户端 " + client.RemoteEndPoint + " 主动断开连接");
clientSockets.Remove(client);
client.Shutdown(SocketShutdown.Both);
client.Close();
return;
}
//清空数据继续接收
buffer = new byte[buffer.Length];
//继续接收这个客户端传来的消息
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, BeginReceiveCallback, client);
}
关闭服务器和所有客户端连接
private void OnDestroy()
{
//首先关闭负责监听连接的Socket
if (listenSocket != null)
{
listenSocket.Close();
Debug.Log("关闭服务器,停止接收客户端消息!");
}
//然后关闭已连接客户端的Socket
if (clientSockets.Count!=0)
{
for (int i = 0; i < clientSockets.Count; i++)
{
Debug.Log("断开客户端:" + clientSockets[i].RemoteEndPoint.ToString());
clientSockets[i].Shutdown(SocketShutdown.Both);
clientSockets[i].Close();
}
}
}
给所有客户端发消息
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("按了空格,给所有客户端发消息");
for (int i = 0; i < clientSockets.Count; i++)
{
clientSockets[i].Send(Encoding.UTF8.GetBytes("Greet"));
}
}
}
源码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
public class CZServer : MonoBehaviour
{
/// <summary>
/// 服务器IP
/// </summary>
public string serverIP = "0.0.0.0";
/// <summary>
/// 服务器端口
/// </summary>
public int serverPoint = 8080;
/// <summary>
/// 负责监听消息的Socket
/// </summary>
Socket listenSocket;
/// <summary>
/// 所有客户端Socket
/// </summary>
List<Socket> clientSockets=new List<Socket>();
/// <summary>
/// 字节流数据
/// </summary>
private byte[] buffer = new byte[1024 * 1024 * 2];
// Start is called before the first frame update
void Start()
{
DebugLocalIP();
StartServer();
}
/// <summary>
/// 打印本地IP
/// </summary>
public void DebugLocalIP()
{
IPAddress[] iPAddresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
for (int i = 0; i < iPAddresses.Length; i++)
{
Debug.Log(iPAddresses[i].ToString());
}
}
/// <summary>
/// 开启服务器,并开始监听客户端连接
/// </summary>
public void StartServer()
{
//新建一个负责监听的Socket
listenSocket= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP地址和端口
IPAddress ip = IPAddress.Parse(serverIP);
IPEndPoint point = new IPEndPoint(ip,serverPoint);
//绑定监听端口
listenSocket.Bind(point);
//设置监听队列
listenSocket.Listen(10);
//开始监听客户端连接并设置连接回调
listenSocket.BeginAccept(BeginAcceptCallBack, listenSocket);
Debug.Log("服务器开启成功");
}
/// <summary>
/// 客户端连接回调
/// </summary>
/// <param name="ar"></param>
private void BeginAcceptCallBack(IAsyncResult ar)
{
//客户端连接成功,新建一个客户端的Socket
Socket clientSocket = listenSocket.EndAccept(ar);
Debug.Log("客户端连接成功 " + clientSocket.RemoteEndPoint.ToString());
//将所有连接的客户端socket都放到列表中
clientSockets.Add(clientSocket);
//给刚才连接的客户端发送Hello
clientSocket.Send(Encoding.UTF8.GetBytes("Hello"));
//开始监听这个客户端发了什么消息,并且设置回调
clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, BeginReceiveCallback, clientSocket);
//继续监听其他客户端连接
listenSocket.BeginAccept(BeginAcceptCallBack, listenSocket);
}
/// <summary>
/// 收到客户端消息回调
/// </summary>
/// <param name="ar"></param>
private void BeginReceiveCallback(IAsyncResult ar)
{
//拿到当前这个客户端的Socket
Socket client = (Socket)ar.AsyncState;
client.EndReceive(ar);
string msg = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Debug.Log("服务器收到客户端 " + client.RemoteEndPoint + " 消息:"+msg);
//如果消息是空的,说明客户端主动断开连接,就要把这个客户端Socket给干掉 Poll 方法将会检查 Socket 的状态
if (client.Poll(-1, SelectMode.SelectRead) && client.Available == 0)
{
Debug.Log("客户端 " + client.RemoteEndPoint + " 主动断开连接");
clientSockets.Remove(client);
client.Shutdown(SocketShutdown.Both);
client.Close();
return;
}
//清空数据继续接收
buffer = new byte[buffer.Length];
//继续接收这个客户端传来的消息
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, BeginReceiveCallback, client);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("按了空格,给所有客户端发消息");
for (int i = 0; i < clientSockets.Count; i++)
{
clientSockets[i].Send(Encoding.UTF8.GetBytes("Greet"));
}
}
}
private void OnDestroy()
{
//首先关闭负责监听连接的Socket
if (listenSocket != null)
{
listenSocket.Close();
Debug.Log("关闭服务器,停止接收客户端消息!");
}
//然后关闭已连接客户端的Socket
if (clientSockets.Count!=0)
{
for (int i = 0; i < clientSockets.Count; i++)
{
Debug.Log("断开客户端:" + clientSockets[i].RemoteEndPoint.ToString());
clientSockets[i].Shutdown(SocketShutdown.Both);
clientSockets[i].Close();
}
}
}
}