Example #1
0
 /// <summary>
 /// Queue a request for data to the database.
 /// The DatabaseRequest will always be executed on the database
 /// thread. It should be used to retrieve data from the database.
 /// The DatabaseCallback will be executed in the loop specified
 /// in the third argument. This can be used to process the data.
 /// </summary>
 /// <typeparam name="T">The type of data you want to request</typeparam>
 /// <param name="request">The request to execute on the database thread. Needs to return collection of data</param>
 /// <param name="callback">The callback to execute in the specified loop when the data has been retrieved</param>
 /// <param name="loop">The loop in which to call the callback</param>
 public static void QueueDatabaseRequest <T>(DatabaseRequest <T> request, DatbaseCallback <T> callback, TickLoop loop) where T : class
 {
     App.Console?.Print($"Queued a DBRequest", Colors.LimeGreen);
     DatabaseLoop.EnqueueAction(() =>
     {
         var results = request.Invoke(Database);
         int count;
         if (results != null)
         {
             count = results.Count;
             loop.EnqueueAction(() => callback.Invoke(results));
         }
         else
         {
             count = 0;
             loop.EnqueueAction(() => callback.Invoke(new List <T>()));
         }
         App.Console?.Print($"Retrieved {count} items from DB, queueing callback", Colors.LimeGreen);
     });
 }
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="socket">客户端Socket对象</param>
        private void ReceiveMessage(Socket socket)
        {
            bool isMain = true;                                              //是否为主端口

            string     clientID         = string.Empty;                      //客户端ID
            IPEndPoint clientIPEndPoint = (IPEndPoint)socket.RemoteEndPoint; //客户端网络终结点

            bool isFirstConnection = true;                                   //是否为首次连接

            byte[] dataBuffer = new byte[1024 * 1024];                       //缓冲区

            bool     isFirstReceive = true;                                  //是否为首次接收数据
            Transmit transmit       = null;                                  //传输对象
            double   dataSize       = 0.0;                                   //数据总大小
            double   receiveBytes   = 0.0;                                   //已接收的字节数
            int      targetPort     = -1;                                    //发送目标端口

            while (true)
            {
                int readBytes = 0;
                if (socket.Poll(-1, SelectMode.SelectRead) == true)
                {
                    if (!ServerState)
                    {
                        break;
                    }
                    try
                    {
                        readBytes = socket.Receive(dataBuffer, dataBuffer.Length, SocketFlags.None);
                        if (readBytes == 0)
                        {
                            if (isMain)
                            {
                                CloseClient(clientID);
                                break;
                            }
                            CloseClientPort(clientID, clientIPEndPoint.Port);
                            break;
                        }
                    }
                    catch (Exception exception)
                    {
                        if (isMain)
                        {
                            CloseClient(clientID, false, exception);
                            break;
                        }
                        CloseClientPort(clientID, clientIPEndPoint.Port, false, exception);
                        break;
                    }
                }

                //首次连接
                if (isFirstConnection)
                {
                    isFirstConnection = false;
                    clientID          = Encoding.UTF8.GetString(dataBuffer, 0, readBytes);
                    if (clientCollection.AddClient(clientID, clientIPEndPoint, socket))
                    {
                        ServerMessage?.Invoke(this, new ServerNotifyEventArgs($"客户端 {clientID}({clientIPEndPoint}) 已连接"));
                    }
                    else
                    {
                        if (!clientCollection.AddPort(clientID, clientIPEndPoint.Port, socket))
                        {
                            break;
                        }
                        isMain = false;
                        ServerMessage?.Invoke(this, new ServerNotifyEventArgs($"客户端 {clientID} 的 {clientIPEndPoint.Port} 端口已连接"));
                    }
                    socket.Send(new byte[] { 1 });
                    continue;
                }

                //首次接收数据
                if (isFirstReceive)
                {
                    isFirstReceive = false;
                    transmit       = BytesConvert.BytesToObject(dataBuffer, readBytes, "MiniSocket.Transmitting") as Transmit;
                    if (transmit?.Parameter == null)
                    {
                        ResetParameter(ref isFirstReceive, ref transmit, ref dataSize, ref receiveBytes);
                        continue;
                    }

                    if (isMain)
                    {
                        string[] parameters = transmit.Parameter.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                        switch (transmit.DataType)
                        {
                        case DataType.Text:
                            if (!Forward(transmit, dataBuffer, readBytes))
                            {
                                return;
                            }
                            break;

                        case DataType.Image:
                            if (parameters.Length == 2)
                            {
                                if (double.TryParse(parameters[1], out dataSize))
                                {
                                    if (!Forward(transmit, dataBuffer, readBytes))
                                    {
                                        return;
                                    }
                                    continue;
                                }
                            }
                            break;

                        case DataType.Request:
                            if (transmit.Parameter.StartsWith("Database"))
                            {
                                if (parameters.Length == 2)
                                {
                                    var result = DatabaseRequest?.Invoke(this, new DatabaseEventArgs(parameters[1], transmit.Object))?.Result;
                                    if (result != null)
                                    {
                                        transmit.Parameter = "Client;RequestResult";
                                        transmit.Object    = result;
                                        byte[] buffer = BytesConvert.ObjectToBytes(transmit);
                                        if (!Forward(transmit, buffer, buffer.Length))
                                        {
                                            return;
                                        }
                                    }
                                }
                            }
                            break;
                        }
                        ResetParameter(ref isFirstReceive, ref transmit, ref dataSize, ref receiveBytes);
                        continue;
                    }
                    if (transmit.DataType == DataType.File)
                    {
                        string[] parameters = transmit.Parameter.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                        if (parameters.Length == 2)
                        {
                            if (double.TryParse(parameters[1], out dataSize))
                            {
                                Transmit requestTransmit = new Transmit()
                                {
                                    SourceID  = transmit.SourceID,
                                    TargetID  = transmit.TargetID,
                                    DataType  = DataType.Request,
                                    Parameter = "Client;AddSocket"
                                };
                                byte[] buffer = BytesConvert.ObjectToBytes(requestTransmit);
                                if (!Forward(requestTransmit, buffer, buffer.Length))
                                {
                                    return;
                                }
                                Thread.Sleep(3000);
                                List <Socket> sockets = clientCollection.GetClientSockets(transmit.TargetID);
                                targetPort = ((IPEndPoint)sockets[sockets.Count - 1].RemoteEndPoint).Port;
                                if (!Forward(transmit, dataBuffer, readBytes, targetPort))
                                {
                                    return;
                                }
                                continue;
                            }
                        }
                    }
                    CloseClientPort(clientID, clientIPEndPoint.Port);
                    return;
                }

                receiveBytes += readBytes; //已接收到的数据累加

                //判断已接收到的数据是否有效
                if (receiveBytes > 0 && receiveBytes <= dataSize)
                {
                    if (!Forward(transmit, dataBuffer, readBytes, targetPort))
                    {
                        break;
                    }
                }
                //判断是否接收完成或数据是否有误
                if (receiveBytes == dataSize || (receiveBytes <= 0 || receiveBytes > dataSize))
                {
                    if (isMain)
                    {
                        ResetParameter(ref isFirstReceive, ref transmit, ref dataSize, ref receiveBytes);
                        continue;
                    }
                    CloseClientPort(clientID, clientIPEndPoint.Port);
                    break;
                }
            }
        }