c#的 socket 这样写对不对啊

2020-12-11 22:23:06 +08:00
 zxCoder

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

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

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;
        }
    }
}
1024 次点击
所在节点    问与答
3 条回复
actorzjp
2020-12-12 00:12:49 +08:00
发到.NET 节点啊
opengps
2020-12-12 08:35:14 +08:00
头部占 5 个细节是协议约定的?你应该识别验证是否头部,不应该跳过
zxCoder
2020-12-12 09:17:03 +08:00
@opengps

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

这里 FromBytes 这个方法是将字节流转化为消息对象,后面那不是跳过,而是把这部分已经转化为消息的字节流去掉,让剩下的字节移到 state.buffer 的前面来

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/734652

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX