V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zxCoder
V2EX  ›  问与答

c#的 socket 这样写对不对啊

  •  
  •   zxCoder · 2020-12-11 22:23:06 +08:00 · 1126 次点击
    这是一个创建于 1461 天前的主题,其中的信息可能已经有所发展或是发生改变。

    异步,长连接,不知道这样子写对不对,在官网例子的基础上改了一点

    大概代码是这样子的,主要改的就是注释的地方

    namespace MongoDB_PBAC_Server {
        public class StateObject {
            public const int BufferSize = 2048;
            public byte[] buffer = new byte[BufferSize];
            public int length;
            public Socket workSocket = null;
        }
    
        public class Server {
            public static ManualResetEvent allDone = new ManualResetEvent(false);
            public static void StartListening() {
                IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
                int port = 33660;
                IPEndPoint point = new IPEndPoint(ipAddress, port);
                Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                try {
                    listener.Bind(point);
                    listener.Listen(100);
                    while (true) {
                        allDone.Reset();
                        listener.BeginAccept(AcceptCallback, listener);
                        allDone.WaitOne();
                    }
                }
                catch (Exception e) {  }
            }
    
            public static void AcceptCallback(IAsyncResult ar) {
                allDone.Set();
                Socket listener = (Socket) ar.AsyncState;
                Socket handler = listener.EndAccept(ar);
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
            }
    
            public static void ReadCallback(IAsyncResult ar) {
                StateObject state = (StateObject) ar.AsyncState;
                Socket handler = state.workSocket;
                int bytesRead = handler.EndReceive(ar);
                state.length += bytesRead;
                if (bytesRead > 0) {
                    // 将缓冲区的字节反序列化为消息对象
                    Message message = Message.FromBytes(state.buffer);
                    if (message != null) {
                        byte[] temp = new byte[StateObject.BufferSize];
                        // 头部占 5 个字节
                        for (int i = 0; i < state.length-(message.length+5); i++) {
                            temp[i] = state.buffer[message.length+5 + i];
                        }
                        state.buffer = temp;
                        state.length -= (message.length+5);
                        Message res = HandleMessage(message);
                        Send(handler, res.ToBytes());
                    }
    
                    // 剩下的继续接收                
                    handler.BeginReceive(
                        state.buffer,
                        state .length,
                        state.buffer.Length - state.length,
                        0,
                        ReadCallback,
                        state);
                }
                else {
                    // 如果接收字节数为 0,就关闭客户端?
                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
            }
    
            private static void Send(Socket handler, byte[] data) {
                handler.BeginSend(data, 0, data.Length, 0, SendCallback, handler);
            }
    
            private static void SendCallback(IAsyncResult ar) {
                try {
                    Socket handler = (Socket) ar.AsyncState;
                    int bytesSent = handler.EndSend(ar);
                }catch (Exception e) {}
            }
    
            private static Message HandleMessage(Message message) {
                return message;
            }
        }
    }
    
    3 条回复    2020-12-12 09:17:03 +08:00
    actorzjp
        1
    actorzjp  
       2020-12-12 00:12:49 +08:00 via iPhone
    发到.NET 节点啊
    opengps
        2
    opengps  
       2020-12-12 08:35:14 +08:00 via Android
    头部占 5 个细节是协议约定的?你应该识别验证是否头部,不应该跳过
    zxCoder
        3
    zxCoder  
    OP
       2020-12-12 09:17:03 +08:00
    @opengps

    ```
    // 将缓冲区的字节反序列化为消息对象
    Message message = Message.FromBytes(state.buffer);
    if (message != null) {}
    ```

    这里 FromBytes 这个方法是将字节流转化为消息对象,后面那不是跳过,而是把这部分已经转化为消息的字节流去掉,让剩下的字节移到 state.buffer 的前面来
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2740 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 14:10 · PVG 22:10 · LAX 06:10 · JFK 09:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.