除了异步实现Socket之外,我们还有常用的方法,如Select,所以我们先了解什么是Select
参考连接:Socket.Select 方法 (System.Net.Sockets) | Microsoft Learn
阅读完之后,我来简要说明一下,这个方法有四个参数,我们关注第一个参数,它是一个List用来存客户端和服务端的Socket,如果有客户端连接过来那么服务端需要Accept,这就需要用到服务端Socket,所以服务端Socket会保存在List当中,而有客户端Socket发消息过来,我们的客户端Socket也会保存在List当中,这样这个List就收集到了需要Accept的Socket和需要Receive的Socket,下面我们来看代码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
#nullable disable
namespace UnityServer
{
internal class Server
{
/// <summary>
/// 服务端Socket
/// </summary>
private static Socket serverSocket;
/// <summary>
/// 客户端Socket以及状态信息的字典
/// </summary>
private static Dictionary<Socket, ClientState> clients = new Dictionary<Socket, ClientState>();
public static void Main()
{
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint iPEndPoint = new IPEndPoint(ip, 8888);
serverSocket.Bind(iPEndPoint);
serverSocket.Listen(0);
Console.WriteLine("服务端启动成功");
List<Socket> socketList = new List<Socket>();
while (true)
{
socketList.Clear();
socketList.Add(serverSocket);
foreach (ClientState s in clients.Values)
{
socketList.Add(s.socket);
}
//检测可读Socket
Socket.Select(socketList, null, null, 1000);
foreach (Socket s in socketList)
{
if (s == serverSocket)
{
Accept(s);
}
else
{
Receive(s);
}
}
}
}
/// <summary>
/// 服务端Accept
/// </summary>
/// <param name="serverSocket"></param>
private static void Accept(Socket serverSocket)
{
Console.WriteLine("Accept");
Socket clientSocket = serverSocket.Accept();
ClientState state = new ClientState();
state.socket = clientSocket;
clients.Add(clientSocket,state);
}
/// <summary>
/// 接收消息以及发送给所有客户端
/// </summary>
/// <param name="clientSocket"></param>
private static void Receive(Socket clientSocket)
{
ClientState state = clients[clientSocket];
int count = clientSocket.Receive(state.readBuff);
//关闭
if (count == 0)
{
clientSocket.Close();
clients.Remove(clientSocket);
Console.WriteLine("有一个客户端断开连接");
return;
}
//发送给所有客户端
string receiveStr = Encoding.UTF8.GetString(state.readBuff, 0, count);
Console.WriteLine("Receive:" + receiveStr);
byte[] sendBytes=Encoding.UTF8.GetBytes(receiveStr);
foreach (ClientState s in clients.Values)
{
s.socket.Send(sendBytes);
}
}
}
}
为了Select和异步都学会,我们采用Select服务端和异步客户端