C# websocket 搭建

一、websocket的搭建(还没有实现序列化的功能)

功能不是太完整,并且有些地方逻辑有点乱,但是基本的登录、注册已经实现,排行没有实现。现在问题是,发送回前端的数据没有序列化,只是发送字符串。

1、实现前后端的连接

    WebSocketServer ws = new WebSocketServer();
    #region 注销
    //ws.NewMessageReceived += new SessionHandler<WebSocketSession, string>(ReceiveMessages);
    //ws.NewSessionConnected += new SessionHandler<WebSocketSession>(ReceiveConnect);
    //ws.SessionClosed += new SessionHandler<WebSocketSession, CloseReason>(SessionClosed);
    //ws.NewDataReceived += new SessionHandler<WebSocketSession, byte[]>( ReceiveData);
    #endregion
    if (!ws.Setup("192.168.0.134", 2018))//IP要和本机相同,否则会报错
    {
        Console.WriteLine("Failed to setup!"); //未设置成功
        Console.ReadKey();
        return;
    }

    if (!ws.Start())
    {
        Console.WriteLine("Failed to start!");
        Console.ReadKey();
        return;//未启动成功
    }

    Console.WriteLine("The server started successfully, press key 'q' to stop it!");
    ws.NewMessageReceived += ReceiveMessages;
    ws.NewSessionConnected += ReceiveConnect;
    ws.SessionClosed += SessionClosed;
    ws.NewDataReceived += ReceiveData;
    
    //如果不是"q",则继续执行
     while (Console.ReadKey().KeyChar != 'q')
        {
            Console.WriteLine();
            continue;
        }

        //Stop the appServer
        ws.Stop();

        Console.WriteLine("The server was stopped!");
        Console.ReadKey();
    }

2、包装各类方法

1>实现握手功能

    static void ReceiveConnect(WebSocketSession session)
    {
        Console.WriteLine("新的连接,即为握手包");
        SendToClient(session, "欢迎新用户");
    }

2>监听用户退出

    static void SessionClosed(WebSocketSession session, CloseReason closeReason)
    {
        lock (_dicLock)
        {
            string key = string.Empty;
            foreach (KeyValuePair<string, WebSocketSession> keyValue in _dic)
            {
                if (keyValue.Value.Equals(session))
                {
                    key = keyValue.Key;
                    break;
                }
            }
            if (key != string.Empty)
            {
                _dic.Remove(key);
            }
        }
        Console.WriteLine("已经退出");
    }

3>接收前端二进制数据,同时实现注册、登录、排行的功能(功能实现方法可能有些不合理,视自己情况而定,而且判断功能是哪个的方法也不是太准确,可以适当调整)

 static void ReceiveData(WebSocketSession session, byte[] data)
    {
        if (data == null || data.Length < 4)
        {
            return;
        }
        //string s = BitConverter.ToString(data,4,data.Length-4);
        uint len = BitConverter.ToUInt32(data, 0);
        int a = len.ToString().Length;//包的长度
        //获取数组的前面四位之后得信息,用来识别前端给的判断信息
        byte[] k = new byte[data.Length - 4];
        Array.Copy(data, 4, k, 0, data.Length - 4);
        //前面四位数组
        byte[] w = new byte[4];
        Array.Copy(data, 0, w, 0, 4);
        MemoryStream msg = new MemoryStream(data);
        //通过这步,主要是获取t.status得值,用来判断实现哪个功能,因为注册、登录、排行.proto中都有status对象
        log1 t = ProtoBuf.Serializer.Deserialize<log1>(msg);
        //byte[] j = new byte[1];
        //Array.Copy(data, 3, j, 0, 1);
        if (t.status == "1001")
        {
            if (a + sizeof(uint) <= data.Length) //长度符合
            {
                logins.log1 m = new logins.log1();
                MemoryStream ms = new MemoryStream(data);
                //BinaryReader br = new BinaryReader(ms);
                //ushort protoId = br.ReadUInt16(); //协议号
                //Type type = typeof(uint); //通过协议号获取
                log1 o = ProtoBuf.Serializer.Deserialize<log1>(ms);//反序列化
                #region 登录信息
                logins.log1 h = (logins.log1)o;
                UserLoginManage ii = new UserLoginManage();
                //调用BLL里面方法,用来判断是否符合要求
                if (ii.UserLogin(h) != null)
                {
                    SendToClient(session, "1001");//登录成功
                    Console.WriteLine("1001登录成功");
                }
                else
                {
                    SendToClient(session, "1002");//登录失败
                    Console.WriteLine("1002登录失败");
                }
                Console.ReadKey();
            }
        }
        #endregion
       
        #region 注册信息
        if (t.status == "1002")
        {
            if (a + sizeof(uint) <= data.Length) //长度符合
            {
                MemoryStream ms = new MemoryStream(k);
                BinaryReader br = new BinaryReader(ms);
                //ushort protoId = br.ReadUInt16(); //协议号
                //Type type = typeof(uint); //通过协议号获取
                reg o = ProtoBuf.Serializer.Deserialize<reg>(ms);//反序列化
                register.reg rr = new register.reg();
                string sql = "select name from dbUserRegister where name='{0}'";
                sql = string.Format(sql, o.userid);
                SqlDataReader objReader = SQLHelper.GetReader(sql);
                if (objReader.Read())
                {
                    rr.userid = objReader["name"].ToString();
                    objReader.Close();
                }
                if (rr.userid != null)
                {
                  
                    SendToClient(session, "1006");//注册失败,用户名已被占用
                    Console.WriteLine("1006用户名已经被占用");
                }
                else
                {
                    UserRegisterManage hh = new UserRegisterManage();
                    //判断是否有输入信息
                    if (hh.UserRegister(o) != null)
                    {
                    
                        SendToClient(session,"1003");//注册成功,有输入信息
                        Console.WriteLine("1003注册成功,有输入信息");
                    }
                    else
                    {
                       
                        SendToClient(session, "1004");//注册失败,没有注册信息
                        Console.WriteLine("1004注册失败,没有注册信息");
                    }
                    Console.ReadLine();
                }
            }
        }
        #endregion
        #region 排行信息
        if (t.status == "1003")
        {
            if (a + sizeof(uint) <= data.Length) //长度符合
            {
                MemoryStream ms = new MemoryStream(k);
                BinaryReader br = new BinaryReader(ms);
                //ushort protoId = br.ReadUInt16(); //协议号
                //Type type = typeof(uint); //通过协议号获取
                Msg.data o = ProtoBuf.Serializer.Deserialize<Msg.data>(ms);//反序列化
                Msg.data ss = (Msg.data)o;
                Msg.data uu = new Msg.data();
                string sqlc = "select score from dbUserRanking where score='{0}'";
                sqlc = string.Format(sqlc, ss.score);
                SqlDataReader objReader = SQLHelper.GetReader(sqlc);
                if (objReader.Read())
                {
                    UserRankingManage nn = new UserRankingManage();
                    string sqld = "select top 3 score from dbUserRanking order by score";
                    SqlDataReader objRead = SQLHelper.GetReader(sqld);
                    if (objRead.Read())
                    {
                        List<Msg.data> list = new List<Msg.data>();
                        while (objRead.NextResult())//读取出所有东西
                        {
                            Msg.data dd = new Msg.data
                            {
                                score = objRead["score"].ToString()
                            };
                            list.Add(dd);
                        }
                        byte[] bytes = new byte[1024];
                        MemoryStream mem = new MemoryStream(bytes);
                        ProtoBuf.Serializer.NonGeneric.Serialize(mem, list);
                        long position = mem.Position;
                        SendToClient(session, typeof(int), bytes, 0, (int)position);
                    }
                   
                }
            }
            #endregion
        }
    }

4>发送string类型数据给客户端(没有区分是哪种消息)

    static void SendToClient(WebSocketSession session,string msg)
    {
        session.Send(msg);
    }

5>通过协议头来发送消息(后来没有通过协议头获取,二十通过protobuf接收前面定义的头信息)

    static void SendToClient(WebSocketSession session, Type type,
        byte[] msg, int offset, int length)
    {
        MemoryStream ms = new MemoryStream(msg);
        BinaryWriter br = new BinaryWriter(ms);
        uint protoId = 0; //通过type获取协议号
        br.Write(protoId); //写入头
        int len = (int)ms.Length;
        br.Write(length + sizeof(uint)); //写入头
        session.Send(msg, offset, length + sizeof(uint) + sizeof(int));
    }

6>群发消息,发给多个客户端

    static void SendToClient(List<WebSocketSession> sessions, string msg)
    {
        foreach (WebSocketSession session in sessions)
        {
            session.Send(msg);
        }
    }
    
    static void SendToClient(List<WebSocketSession> sessions, byte[] msg, int offset, int length)
    {
        foreach (WebSocketSession session in sessions)
        {
            session.Send(msg, offset, length);
        }
    }

.proto设计:https://blog.csdn.net/qq_42375267/article/details/84567626

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值