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

### 回答1: Unity是一种跨平台的游戏开发引擎,它的网络功能强大,并支持搭建WebSocket服务器。以下是搭建WebSocket服务器的一般步骤: 1. 导入WebSocket库:首先需要在Unity项目中导入WebSocket库。可以通过在Unity Asset Store中搜索和下载适用于Unity的WebSocket库,也可以在GitHub等平台上找到最新的WebSocket库。 2. 创建服务器脚本:在Unity中,可以使用C#编写服务器脚本。创建一个新的C#脚本,并将其附加到游戏对象上,作为WebSocket服务器的入口点。 3. 初始化WebSocket服务器:在服务器脚本中,需要使用WebSocket库提供的方法来初始化服务器。这通常涉及指定服务器的IP地址和端口号,并设置其他配置选项(如是否使用SSL等)。 4. 监听连接:通过调用WebSocket库提供的方法,可以开始监听连接请求。一旦有客户端连接到服务器,就会触发特定的事件,我们可以在事件处理程序中编写处理逻辑。 5. 处理消息:一旦客户端与服务器成功连接,它们可以通过WebSocket发送消息。服务器需要编写逻辑来处理接收到的消息,并根据其内容采取相应的操作。可以使用WebSocket库提供的方法来解析消息并回复客户端。 6. 关闭连接:当客户端断开连接时,服务器也需要相应地关闭连接。可以编写代码来处理关闭连接的事件,并进行清理工作。 7. 测试服务器:最后,可以启动Unity游戏,并使用WebSocket客户端连接到服务器进行测试。可以通过发送和接收消息来验证服务器的功能是否正常。 总的来说,通过以上步骤,我们可以在Unity中搭建一个WebSocket服务器。服务器脚本负责初始化服务器,监听和处理连接,接收和发送消息,并关闭连接。 ### 回答2: Unity是一款强大的游戏开发引擎,它提供了许多网络功能,包括搭建WebSocket服务器。WebSocket是一种全双工通信协议,可以在客户端和服务器之间实现实时通信。 要在Unity中搭建WebSocket服务器,可以使用第三方库或插件。以下是一个基本的步骤: 1. 导入WebSocket库:首先,在Unity的Asset Store中搜索并导入WebSocket库。例如,可以使用SocketIoClientDotNet或websocket-sharp等库。 2. 创建服务器脚本:在Unity中创建一个脚本,用于管理WebSocket服务器的逻辑。这个脚本需要实现WebSocket服务器的初始化、连接管理以及消息处理等功能。 3. 初始化服务器:在脚本中,使用WebSocket库来初始化服务器。根据所选的库,有关如何进行初始化和设置服务器的示例代码可以在其文档中找到。 4. 监听连接:设置服务器监听指定的端口,以便能够接收客户端的连接请求。 5. 处理连接和消息:当客户端连接到服务器时,将触发一个事件。在事件处理程序中,可以实现客户端的验证、连接管理以及消息处理等逻辑。 6. 发送和接收消息:通过WebSocket库的API,可以发送和接收消息。根据具体需求,可以实现自定义的消息协议和消息处理逻辑。 7. 关闭服务器:当服务器不再需要时,可以调用相应的API来关闭服务器。 在Unity中搭建WebSocket服务器可以实现多种功能,例如实时聊天、多人游戏、实时数据推送等。通过WebSocket的全双工通信特性,可以提供更好的用户体验和交互性。 需要注意的是,搭建WebSocket服务器需要熟悉网络编程和Unity的开发环境。同时,根据项目的需求,可能需要进一步扩展服务器的功能和优化性能。 ### 回答3: Unity是一款多平台游戏开发引擎,虽然它主要用于创建游戏,但也可以用于其他类型的实时应用程序的开发,其中包括搭建WebSocket服务器。 在Unity中搭建WebSocket服务器可以通过使用第三方库或扩展来实现。以下是一个使用Best HTTP库来搭建WebSocket服务器的简要步骤: 首先,下载并导入Best HTTP库到Unity项目中。它是一个功能强大的HTTP库,可以与常见的WebSocket实现一起使用。 接下来,创建一个新的C#脚本,在脚本中编写服务器的逻辑。需要使用Best HTTP库中的WebSocket组件。 在脚本中,你可以设置WebSocket服务器的IP地址和端口号,并定义WebSocket连接的回调函数。可以在服务器和客户端之间传递消息,并处理各种富文本通讯协议。 在Unity中,你可以创建一个空对象并附加刚才编写的脚本。当游戏或应用程序运行时,这个对象将充当WebSocket服务器。 最后,你可以使用网络工具,例如Chrome的WebSocket调试工具或自定义的客户端应用程序,通过WebSocket协议连接到Unity中运行的服务器。通过这种方式,你可以在Unity中接收和处理客户端发送的消息。 总结起来,Unity可以使用Best HTTP库来搭建WebSocket服务器。你需要导入Best HTTP库,编写服务器逻辑的脚本,并使用WebSocket组件来管理WebSocket连接和处理消息。然后,你可以在Unity中运行服务器,并使用网络工具与之建立WebSocket连接。这样,你就可以在Unity中实现WebSocket服务器的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值