using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace Core { public class PServer { private Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); private ConcurrentDictionary Rooms { get; } = new ConcurrentDictionary(); public PServer(string ip, int port, int backlog) { IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ip), port); serverSocket.Bind(endPoint); serverSocket.Listen(backlog); } public async Task StartAsync() { while (true) { Socket clientSocket = await serverSocket.AcceptAsync(); Console.WriteLine($"[{DateTime.Now}] Accept client: {clientSocket.RemoteEndPoint}"); ThreadPool.QueueUserWorkItem(RunAsync, clientSocket); } } private async void RunAsync(object? sender) { if (sender == null) return; Socket clientSocket = (Socket)sender; byte[] headerBuffer = new byte[2]; string id = ""; string nickname = ""; string roomName = ""; while (true) { // header buffer int n1 = await clientSocket.ReceiveAsync(headerBuffer, SocketFlags.None); if (n1 < 1) { Console.WriteLine($"[{DateTime.Now}] Disconnect client - {clientSocket.RemoteEndPoint}"); clientSocket.Dispose(); return; } else if (n1 == 1) { await clientSocket.ReceiveAsync(new ArraySegment(headerBuffer, 1, 1), SocketFlags.None); } // data buffer short dataSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(headerBuffer)); byte[] dataBuffer = new byte[dataSize]; int totalRecv = 0; while (totalRecv < dataSize) { int n2 = await clientSocket.ReceiveAsync(new ArraySegment(dataBuffer, totalRecv, dataSize - totalRecv), SocketFlags.None); totalRecv += n2; } PacketType packetType = (PacketType)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(dataBuffer)); if (packetType == PacketType.LoginRequest) { LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer); Console.WriteLine($"[{DateTime.Now}] LoginRequest - Id: {requestPacket.Id}, Nickname: {requestPacket.NickName}"); id = requestPacket.Id; nickname = requestPacket.NickName; LoginResponsePacket responsePacket = new LoginResponsePacket(StatusCode.Success); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); } else if (packetType == PacketType.CreateRoomRequest) { CreateRoomRequestPacket requestPacket = new CreateRoomRequestPacket(dataBuffer); Room room = new Room(); if (Rooms.TryAdd(requestPacket.RoomName, room)) { roomName = requestPacket.RoomName; room.Users.TryAdd(id, nickname); Console.WriteLine($"[{DateTime.Now}] CreateRoomRequest - RoomName: {roomName}, id: {id}, nickname: {nickname}"); CreateRoomResponsePacket responsePacket = new CreateRoomResponsePacket(StatusCode.Success); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); } else { Console.WriteLine($"[{DateTime.Now}] CreateRoomRequest failed - RoomName: {requestPacket.RoomName}"); CreateRoomResponsePacket responsePacket = new CreateRoomResponsePacket(StatusCode.Failed); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); } } else if (packetType == PacketType.RoomListRequest) { RoomListResponsePacket packet = new RoomListResponsePacket(Rooms.Keys); await clientSocket.SendAsync(packet.Serialize(), SocketFlags.None); } else if (packetType == PacketType.EnterRoomRequest) { EnterRoomRequestPacket requestPacket = new EnterRoomRequestPacket(dataBuffer); if (Rooms.TryGetValue(requestPacket.RoomName, out var room)) { roomName = requestPacket.RoomName; room.Users.TryAdd(id, nickname); Console.WriteLine($"[{DateTime.Now}] EnterRoomRequest - RoomName: {roomName}, id: {id}, nickname: {nickname}"); EnterRoomResponsePacket responsePacket = new EnterRoomResponsePacket(StatusCode.Success); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); } else { Console.WriteLine($"[{DateTime.Now}] EnterRoomRequest failed - RoomName: {requestPacket.RoomName}"); EnterRoomResponsePacket responsePacket = new EnterRoomResponsePacket(StatusCode.Failed); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); } } } } } }