using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.IO; using System.Runtime.InteropServices; using System.Threading; using PSO2SERVER.Models; using PSO2SERVER.Protocol; using System.Threading.Tasks; using PSO2SERVER.Protocol.Packets; namespace PSO2SERVER { public enum QueryMode { ShipList,/*12100 - 12900*/ AuthList } public class QueryServer { public static List RunningServers = new List(); private readonly QueryMode _mode; private readonly int _port; public QueryServer(QueryMode mode, string desc, int port) { _mode = mode; _port = port; var queryTask = Task.Run(() => RunAsync()); RunningServers.Add(queryTask); Logger.WriteInternal("[监听] 监听" + desc + "端口 " + port); } private async Task RunAsync() { Func connectionHandler; switch (_mode) { case QueryMode.AuthList: connectionHandler = DoBlockBalanceAsync; break; case QueryMode.ShipList: connectionHandler = DoShipListAsync; break; default: connectionHandler = DoShipListAsync; break; } var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { Blocking = true }; var ep = new IPEndPoint(IPAddress.Any, _port); serverSocket.Bind(ep); // TODO: Custom bind address. serverSocket.Listen(5); while (true) { var newConnection = await Task.Factory.FromAsync(serverSocket.BeginAccept, serverSocket.EndAccept, null); _ = connectionHandler(newConnection); // Fire-and-forget pattern for handling connections } } public ShipStatus CheckShipStatus(int port) { //TODO 还有其他状态要判断 if (PortChecker.IsPortListening(port)) { return ShipStatus.Online; } return ShipStatus.Offline; } private async Task DoShipListAsync(Socket socket) { var entries = new List(); for (var i = 1; i <= 10; i++) { var entry = new ShipEntry { order = (ushort)i, number = (uint)i, //status = i == 2 ? ShipStatus.Online : ShipStatus.Full, // Maybe move to Config? status = CheckShipStatus(ServerApp.ServerShipProt + (100 * (i - 1))), // Maybe move to Config? name = String.Format("Ship{0:0#}", i), ip = ServerApp.BindAddress.GetAddressBytes() }; entries.Add(entry); } var shiplistpacket = new ShipListPacket(entries, (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds, 1).GetPacketBytes(); await Task.Factory.FromAsync( (cb, state) => socket.BeginSend(shiplistpacket, 0, shiplistpacket.Length, SocketFlags.None, cb, state), socket.EndSend, null); socket.Close(); } private async Task DoBlockBalanceAsync(Socket socket) { var balancepacket = new BlockBalancePacket("test", 12205).GetPacketBytes(); await Task.Factory.FromAsync( (cb, state) => socket.BeginSend(balancepacket, 0, balancepacket.Length, SocketFlags.None, cb, state), socket.EndSend, null); socket.Close(); } } }