前言
在开发一些展览馆项目时需要Pad通过局域网控制馆内各个设备的状态,但展览馆又不允许连接外网,故需要局域网多客户端Socket通信。
服务端代码如下
using System.Net.Sockets;
using System.Net;
using System.Text;
using Newtonsoft.Json;
public static class SocketServer
{
public static Socket serverSocket;
public static List<Socket> clientSockets = new List<Socket>();
public static async Task Init()
{
int port = 10000;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Any;
IPEndPoint endPoint = new IPEndPoint(ipAddress, port);
serverSocket.Bind(endPoint);
serverSocket.Listen(10);
Console.WriteLine("服务器正在监听端口 {0}...", port);
while (true)
{
// 异步等待并接受客户端连接
Socket clientSocket = await Task.Run(() => serverSocket.Accept());
Console.WriteLine("客户端已连接");
clientSockets.Add(clientSocket);
// 为每个客户端启动一个异步任务来接收消息
_ = Task.Run(() => ReceiveMessage(clientSocket)); // 异步接收消息,不阻塞主线程
}
}
}
服务端不实现任何业务,故用Console程序,提高稳定性。此代码同样适用于Unity,无需改动。
接收消息方法代码如下
public static async Task ReceiveMessage(Socket clientSocket)
{
byte[] buffer = new byte[1024];
while (true)
{
int a = clientSocket.Receive(buffer);
if (a > 0)
{
string serverResponse = Encoding.UTF8.GetString(buffer, 0, a);
Console.WriteLine("serverResponse ");
}
}
}
发送消息方法代码如下
public static int SendMessage(Socket clientSocket, string data)
{
return clientSocket.Send(Encoding.UTF8.GetBytes(data));
}
clientSockets列表中包含所有连接进来的客户端,在客户端连接成功后向服务端发送自己的ID,可以随后在服务端把ID和Socket存成字典方便访问。
Unity客户端代码如下
public static class Client
{
public static Socket clientSocket;
// 连接到服务器并进行通信
public static async Task ConnectToServerAsync()
{
// 服务器地址和端口
string serverIP = "127.0.0.1";
int port = 10000;
// 创建 TCP 套接字,连接服务器
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(serverIP), port);
try
{
// 异步连接到服务器
await Task.Factory.StartNew(() => clientSocket.Connect(endPoint));
Debug.Log("已连接到服务器");
SendMessage("client已连接,ID: 3278947238947923847");
// 在这里添加一个循环,以便不断与服务器进行通信
// 注意:这个连接将会保持打开状态,直到你手动断开连接
ReceiveMessage();
}
catch (Exception ex)
{
Debug.LogError("连接失败: " + ex.Message);
}
}
public static async Task SendMessage(string message)
{
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await Task.Run(() => clientSocket.Send(messageBytes));
Debug.Log(message);
}
public static async Task ReceiveMessage()
{
byte[] buffer = new byte[1024];
int bytesRead;
string serverResponse;
while (true)
{
// 异步接收服务器的响应
bytesRead = await Task.Factory.StartNew(() => clientSocket.Receive(buffer));
serverResponse = Encoding.UTF8.GetString(buffer, 0, bytesRead);
if (!string.IsNullOrEmpty(serverResponse))
{
Debug.Log("收到服务器消息: " + serverResponse);
}
}
}
// 关闭连接的方法
public static void CloseConnection()
{
if (clientSocket != null && clientSocket.Connected)
{
clientSocket.Close();
Debug.Log("连接已关闭");
}
}
}