예제 #1
0
        /// <summary>
        /// 开始监听
        /// </summary>
        private static Task StartAsync()
        {
            return(Task.Run(() => {
                _webSocketServer.Start(socket =>
                {
                    socket.OnOpen = () =>   //连接建立事件
                    {
                        //获取客户端信息
                        MessageAuthKey messageAuthKey = GetAppAuthKey(socket);
                        if (null == messageAuthKey)
                        {
                            return;
                        }
                        if (AddAgentSocket(socket, messageAuthKey))
                        {
                            LOG.Info(DateTime.Now.ToString() + $"|服务器:和客户端:{messageAuthKey.AgentType},{messageAuthKey.AppId} 建立WebSock连接!");
                        }
                    };
                    socket.OnClose = () =>  //连接关闭事件
                    {
                        // string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                        MessageAuthKey messageAuthKey = GetAppAuthKey(socket);
                        if (null == messageAuthKey)
                        {
                            return;
                        }
                        if (RemoveAgentSocket(messageAuthKey))
                        {
                            LOG.Info(DateTime.Now.ToString() + $"|服务器:和客户端:{messageAuthKey.AgentType},{messageAuthKey.AppId}断开WebSock连接!");
                        }
                    };
                    socket.OnMessage = message =>
                    {
                        // 接受客户端消息事件
                        SendAsync(socket, message);
                    };
                    socket.OnBinary = file => {
                        // 传入文件
                        string path = ("D:/test.txt");
                        //创建一个文件流
                        FileStream fs = new FileStream(path, FileMode.Create);

                        //将byte数组写入文件中
                        fs.Write(file, 0, file.Length);
                        //所有流类型都要关闭流,否则会出现内存泄露问题
                        fs.Close();
                    };
                });
            }));
        }
예제 #2
0
        /// <summary>
        /// 获取客户端ID
        /// </summary>
        /// <param name="socket"></param>
        /// <returns></returns>
        private static MessageAuthKey GetAppAuthKey(IWebSocketConnection socket)
        {
            MessageAuthKey      messageAuthKey = null;
            NameValueCollection queryParams    = UriUtil.GetQueryString(socket.ConnectionInfo.Path);
            string appKey = queryParams["appKey"];
            string appId  = queryParams["appId"];
            // string authKeyStr =socket.ConnectionInfo.Path.Substring(socket.ConnectionInfo.Path.LastIndexOf("?") + 1);
            string callbackMsg = "";

            if (string.IsNullOrEmpty(appKey) || string.IsNullOrEmpty(appId))
            {
                callbackMsg = $"appKey或appId 信息不存在,连接被拒绝";
                LOG.Error(callbackMsg);
                socket.Send(callbackMsg);
                socket.Close();
                return(null);
            }
            try
            {
                // 获取agent类型,支持多端同时连接
                EnumUserAgentType enumUserAgentType = NetAssist.GetUserAgentType(socket.ConnectionInfo.Headers["User-Agent"]);
                string            agentType         = EnumUtil.GetEnumName <EnumUserAgentType>((int)enumUserAgentType);

                if (appId_Agent_AuthKeyMap.ContainsKey(appId))
                {
                    if (appId_Agent_AuthKeyMap[appId].ContainsKey(agentType))
                    {
                        return(appId_Agent_AuthKeyMap[appId][agentType]);
                    }
                }
                messageAuthKey = new MessageAuthKey
                {
                    AppId     = appId,
                    AppKey    = appKey,
                    AgentType = agentType
                };

                // @TODO 验证appkey的有限性和appId是否唯一
                return(messageAuthKey);
            }
            catch (Exception ex)
            {
                LOG.Error(ex, ex.Message);
                callbackMsg = $"连接信息缺失,连接被拒绝。详情:{ex.Message}";
                socket.Send(callbackMsg);
                socket.Close();
                return(null);
            }
        }
예제 #3
0
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private static Task <Boolean> SendAsync(IWebSocketConnection socket, string message)
        {
            return(Task.Run(() => {
                MessageAuthKey fromClientId = GetAppAuthKey(socket);
                if (null == fromClientId)
                {
                    return false;
                }
                MessageBody messageBody = JsonConvert.DeserializeObject <MessageBody>(message);
                // string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort;
                LOG.Info(DateTime.Now.ToString() + $"|服务器:【收到】来客户端:{fromClientId.AppId}的信息:\n" + message);
                // 判断同一个appId下多端
                if (appId_Agent_SocketsMap.ContainsKey(messageBody.To))
                {
                    IDictionary <string, IWebSocketConnection> agents = appId_Agent_SocketsMap[messageBody.To];
                    foreach (var agent in agents)
                    {
                        // 说明肯定在线
                        LOG.Info($"客户端[{messageBody.To}]在线,设备类型[{agent.Key}],发送在线消息");
                        IWebSocketConnection desSocket = agent.Value;

                        MessageBody desSendMsgBody = new MessageBody
                        {
                            From = fromClientId.AppId,
                            To = messageBody.To,
                            ChannelType = messageBody.ChannelType,
                            Payload = messageBody.Payload
                        };
                        LOG.Info(DateTime.Now.ToString() + $"|服务器:【发出】消息,来源:{fromClientId.AppId},目的:{messageBody.To}\n,内容:{messageBody.Payload}");
                        desSocket.Send(JsonConvert.SerializeObject(desSendMsgBody));
                    }
                }
                else
                {
                    LOG.Info($"客户端[{messageBody.To}]离线,发送离线消息");
                    // TODO 保存离线消息
                }
                return true;
            }));
        }
예제 #4
0
        /// <summary>
        /// 移除某类客户端连接
        /// </summary>
        /// <param name="messageAuthKey"></param>
        private static Boolean RemoveAgentSocket(MessageAuthKey messageAuthKey)
        {
            //如果存在这个客户端,那么对这个socket进行移除
            if (appId_Agent_SocketsMap.ContainsKey(messageAuthKey.AppId) &&
                appId_Agent_SocketsMap[messageAuthKey.AppId].ContainsKey(messageAuthKey.AgentType))
            {
                //注:Fleck中有释放
                //关闭对象连接
                //if (dic_Sockets[clientUrl] != null)
                //{
                //dic_Sockets[clientUrl].Close();
                //}
                appId_Agent_SocketsMap[messageAuthKey.AppId].Remove(messageAuthKey.AgentType);
                appId_Agent_AuthKeyMap[messageAuthKey.AppId].Remove(messageAuthKey.AgentType);
            }
            // 删除分布式缓存记录
            IDictionary <string, HashSet <string> > node_agentTypesMap = ServiceFactory.CacheService.Get <IDictionary <string, HashSet <string> > >(messageAuthKey.AppId);

            if (node_agentTypesMap != null)
            {
                if (node_agentTypesMap.ContainsKey(GetNodeKey()))
                {
                    HashSet <string> agentTypes = node_agentTypesMap[GetNodeKey()];
                    if (agentTypes.Remove(messageAuthKey.AgentType))
                    {
                        LOG.Info($"清理缓存appId[{messageAuthKey.AppId}],agentType[{messageAuthKey.AgentType}]记录");
                        ServiceFactory.CacheService.ReplaceAsync(messageAuthKey.AppId, node_agentTypesMap);
                    }
                    else
                    {
                        LOG.Info($"没有找到缓存appId[{messageAuthKey.AppId}],agentType[{messageAuthKey.AgentType}]记录");
                    }
                }
            }
            return(true);
        }
예제 #5
0
        /// <summary>
        /// 添加某类客户端连接
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="messageAuthKey"></param>
        private static Boolean AddAgentSocket(IWebSocketConnection socket, MessageAuthKey messageAuthKey)
        {
            // 上锁
            lock (_LOCK_OBJ)
            {
                // 先判断分布式缓存中是否已经有对应的socket
                IDictionary <string, HashSet <string> > node_agentTypesMap = ServiceFactory.CacheService.Get <IDictionary <string, HashSet <string> > >(messageAuthKey.AppId);
                if (node_agentTypesMap != null)
                {
                    // 当前用户id下跟多少个node建立了socket连接
                    bool hasSameAgentType = false;
                    foreach (var node_agentTypesPair in node_agentTypesMap)
                    {
                        // 排除当前节点
                        if (Object.Equals(node_agentTypesPair.Key, GetNodeKey()))
                        {
                            continue;
                        }
                        HashSet <string> agentTypes = node_agentTypesPair.Value;
                        if (agentTypes.Contains(messageAuthKey.AgentType))
                        {
                            hasSameAgentType = true;
                            // 说明需要踢掉其它节点同一个设备的socket
                            // 发消息
                            KafkaProducer.Send(nameof(EnumMessageType.KICK), JsonConvert.SerializeObject(new KickMessageBody()
                            {
                                AppId     = messageAuthKey.AppId,
                                AgentType = messageAuthKey.AgentType,
                                NodeKey   = node_agentTypesPair.Key
                            }));
                        }
                    }
                    if (!hasSameAgentType)
                    {
                        // 如果其它节点没有相同的设备类型,则把这个设备类型添加到当前节点
                        node_agentTypesMap[GetNodeKey()].Add(messageAuthKey.AgentType);
                        // 添加到分布式缓存中
                        ServiceFactory.CacheService.ReplaceAsync(messageAuthKey.AppId, node_agentTypesMap);
                    }
                }
                else
                {
                    // 添加到分布式缓存
                    node_agentTypesMap = new Dictionary <string, HashSet <string> >
                    {
                        [GetNodeKey()] = new HashSet <string>()
                        {
                            messageAuthKey.AgentType
                        }
                    };
                    ServiceFactory.CacheService.AddAsync(messageAuthKey.AppId, node_agentTypesMap);
                }

                IDictionary <string, IWebSocketConnection> agentSocket = null;
                if (appId_Agent_SocketsMap.ContainsKey(messageAuthKey.AppId))
                {
                    agentSocket = appId_Agent_SocketsMap[messageAuthKey.AppId];
                    if (agentSocket.ContainsKey(messageAuthKey.AgentType))
                    {
                        // 强制踢人
                        // TODO 后续应该需要客户端主动触发确认才踢掉
                        agentSocket[messageAuthKey.AgentType].Close();
                    }
                    agentSocket[messageAuthKey.AgentType] = socket;
                }
                else
                {
                    agentSocket = new Dictionary <string, IWebSocketConnection>
                    {
                        [messageAuthKey.AgentType] = socket
                    };
                    appId_Agent_SocketsMap.Add(messageAuthKey.AppId, agentSocket);
                }
                IDictionary <string, MessageAuthKey> agentAuthkey = null;
                if (appId_Agent_AuthKeyMap.ContainsKey(messageAuthKey.AppId))
                {
                    agentAuthkey = appId_Agent_AuthKeyMap[messageAuthKey.AppId];
                    if (!agentAuthkey.ContainsKey(messageAuthKey.AgentType))
                    {
                        agentAuthkey[messageAuthKey.AgentType] = messageAuthKey;
                    }
                }
                else
                {
                    agentAuthkey = new Dictionary <string, MessageAuthKey>
                    {
                        [messageAuthKey.AgentType] = messageAuthKey
                    };
                    appId_Agent_AuthKeyMap.Add(messageAuthKey.AppId, agentAuthkey);
                }

                return(true);
            }
        }