Пример #1
0
        /// <summary>
        /// 启动WS服务端
        /// </summary>
        /// <exception cref="SoraServerIsRuningException">已有服务器在运行</exception>
        public async ValueTask StartServer()
        {
            if (!serverReady)
            {
                return;
            }
            //检查是否已有服务器被启动
            if (NetUtils.serviceExitis)
            {
                throw new SoraServerIsRuningException();
            }
            //启动服务器
            Server.Start(socket =>
            {
                //接收事件处理
                //获取请求头数据
                if (!socket.ConnectionInfo.Headers.TryGetValue("X-Self-ID",
                                                               out var selfId) ||          //bot UID
                    !socket.ConnectionInfo.Headers.TryGetValue("X-Client-Role",
                                                               out var role))              //Client Type
                {
                    return;
                }

                //请求路径检查
                var isLost = role switch
                {
                    "Universal" => !socket.ConnectionInfo.Path.Trim('/')
                    .Equals(Config.UniversalPath.Trim('/')),
                    _ => true
                };
                if (isLost)
                {
                    socket.Close();
                    Log.Warning("Sora",
                                $"关闭与未知客户端的连接[{socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}],请检查是否设置正确的监听地址");
                    return;
                }

                //打开连接
                socket.OnOpen = () =>
                {
                    //获取Token
                    if (socket.ConnectionInfo.Headers.TryGetValue("Authorization",
                                                                  out var headerValue))
                    {
                        var token = headerValue.Split(' ')[1];
                        Log.Debug("Server", $"get token = {token}");
                        //验证Token
                        if (!token.Equals(this.Config.AccessToken))
                        {
                            return;
                        }
                    }

                    //向客户端发送Ping
                    socket.SendPing(new byte[] { 1, 2, 5 });
                    //事件回调
                    ConnManager.OpenConnection(role, selfId, socket,
                                               socket.ConnectionInfo.Id);
                    Log.Info("Sora",
                             $"已连接客户端[{socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}]");
                };
                //关闭连接
                socket.OnClose = () =>
                {
                    //移除原连接信息
                    if (ConnectionManager.ConnectionExitis(socket.ConnectionInfo.Id))
                    {
                        ConnManager.CloseConnection(role, selfId,
                                                    socket.ConnectionInfo.Id);
                    }

                    Log.Info("Sora",
                             $"客户端连接被关闭[{socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}]");
                };
                //上报接收
                socket.OnMessage = (message) =>
                {
                    //处理接收的数据
                    if (!ConnectionManager.ConnectionExitis(socket.ConnectionInfo.Id))
                    {
                        return;
                    }
                    //进入事件处理和分发
                    Task.Run(() =>
                    {
                        this.Event
                        .Adapter(JObject.Parse(message),
                                 socket.ConnectionInfo.Id);
                    });
                };
            });
            Log.Info("Sora", $"Sora WebSocket服务器正在运行[{Config.Location}:{Config.Port}]");
            //启动心跳包超时检查计时器
            this.HeartBeatTimer = new Timer(ConnManager.HeartBeatCheck, null,
                                            new TimeSpan(0, 0, 0, (int)Config.HeartBeatTimeOut, 0),
                                            new TimeSpan(0, 0, 0, (int)Config.HeartBeatTimeOut, 0));
            NetUtils.serviceExitis = true;

            await Task.Delay(-1);
        }