V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
exqibao
V2EX  ›  C#

使用 C#的 HPSocket 的一个问题

  •  
  •   exqibao · 2023-07-17 10:33:18 +08:00 · 1137 次点击
    这是一个创建于 493 天前的主题,其中的信息可能已经有所发展或是发生改变。

    使用 hpSocket 写程序分服务端和客户端,服务端收到客户端的一个消息,服务端会响应多个信息给客户端,但客户端只收到部分信息,收到的包都是完整的。

    服务端断点时,一个一个看客户端又能收到,关闭断点有低概率收到完整,大概率又收不完全。

    其实循环里面只用发一次,调试故意发 5 次,至少收到 1 次,但没试过 5 次都全收到,除非卡着断点一个一个 Send 走。

                // 创建其他玩家
                foreach (var model in DALManager.Instance.UserDal.GetAllUserModel())
                {
                    Server.Send(connid, MessageType.Type_User, MessageType.User_Create_S, model.ID, model.UserInfo.ModelID,
                        model.Point);
                    Server.Send(connid, MessageType.Type_User, MessageType.User_Create_S, model.ID, model.UserInfo.ModelID,
                        model.Point);
                    Server.Send(connid, MessageType.Type_User, MessageType.User_Create_S, model.ID, model.UserInfo.ModelID,
                        model.Point);
                    Server.Send(connid, MessageType.Type_User, MessageType.User_Create_S, model.ID, model.UserInfo.ModelID,
                        model.Point);
                    Server.Send(connid, MessageType.Type_User, MessageType.User_Create_S, model.ID, model.UserInfo.ModelID,
                        model.Point);
                }
    

    封装的 Send 方法;

            public static void Send(IntPtr connid, byte type, int command, params object[] content)
            {
                Message message = new Message(type, command, content);
                byte[] bytes = Message.ToBytes(message);
                server.Send(connid, bytes, bytes.Length);
            }
    

    hp-socket 的代码了;

        public bool Send(IntPtr connId, byte[] bytes, int length)
        {
          GCHandle gcHandle = GCHandle.Alloc((object) bytes, GCHandleType.Pinned);
          bool flag = HPSocket.Sdk.Server.HP_Server_Send(this.SenderPtr, connId, gcHandle.AddrOfPinnedObject(), length);
          this.SysErrorCode.Value = flag ? 0 : Sys.SYS_GetLastError();
          gcHandle.Free();
          return flag;
        }
    

    似乎连续总是会丢失后面的,有大佬知道问题在哪吗?

    5 条回复    2023-12-02 18:36:25 +08:00
    hankai17
        1
    hankai17  
       2023-07-17 10:34:50 +08:00
    粘包警察在此
    hankai17
        2
    hankai17  
       2023-07-17 10:39:47 +08:00
    是 tcp 吧
    看看 send 返回值
    不是 go 的协程模型吧 感觉上层调用 send 了 底层有缓存没有及时 flush?
    opengps
        3
    opengps  
       2023-07-17 10:43:59 +08:00
    看起来就是粘包问题
    exqibao
        4
    exqibao  
    OP
       2023-07-17 10:59:28 +08:00   ❤️ 1
    @hankai17 @opengps 感谢,看视频没有粘包的处理过程,以为框架有粘包,客户端接收的包是分开的,检查包大小确实后面的包都合并一起了。
    coder001
        5
    coder001  
       355 天前
    在 C#玩 TCP 当然是 Kestrel ,微软自家出品的 Socket 封装,客户端和服务端都能用,用上它之后再也不用自己操心缓冲区了,PDU 边界(低情商俗称:粘包分包)什么的更是雕虫小技

    https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.server.kestrel.transport.sockets.socketconnectioncontextfactory.create?view=aspnetcore-8.0
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3264 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 12:06 · PVG 20:06 · LAX 04:06 · JFK 07:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.