• C# 简单封装异步Socket Server


    前言:最近准备做一个多人在线小游戏的来着,因为没学过udp所以准备用以前学JavaScript时候学来的socket做一个,结果遇到bug裂开了,后来一想socket效率确实不太够然后就没修bug了,但是现在心血来潮把当时写的屎山一样的socket代码刨了一下,简单的封装了一个类。当然,是真的很简单的封装,甚至我自己都不确保能用的那种......

    编译器是Microsoft Visual Studio 2022,没改过啥东西,用原生代码码的。

    目前能想到但不想处理的问题直接列出来得了:

    1. 这种破烂异步的使用放到C++里会爆栈的不知道C#怎么说
    2. 客户端断连的时候估计这边接收不到断连的消息,一个巨大的bug等我有时间了修吧
    3. 单次收到socket后容纳字符的byte数组大小是1024,这个可以自己调整,但是得注意一下这个不是自适应大小的。

    代码部分(完整代码,使用方法在下面)

    下面是初版的代码,不知道之后有没有兴致改改:

    1. public class Cilent
    2. {
    3. //开放的接口部分
    4. public static void SocketOn(string IP, Int32 port, int MaxListen = 100)
    5. {
    6. socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    7. socket.Bind(new IPEndPoint(IPAddress.Parse(IP), port));
    8. socket.Listen(MaxListen);
    9. socket.BeginAccept(AcceptCallBack, null);
    10. }
    11. public static Actionstring>? GetMsg;
    12. public void Send(string msg)
    13. {
    14. if (!cilent.Connected) return;
    15. cilent.Send(Encoding.UTF8.GetBytes(msg));
    16. }
    17. //不开放的部分
    18. private static Socket? socket;
    19. private static void AcceptCallBack(IAsyncResult ar)
    20. {
    21. if (socket == null) return;
    22. Cilent Get = new Cilent(socket.EndAccept(ar));
    23. Get.cilent.BeginReceive(Get.data, 0, 1024, SocketFlags.None, Get.ReceiveCallBack, null);
    24. socket.BeginAccept(AcceptCallBack, null);
    25. }
    26. private void ReceiveCallBack(IAsyncResult ar)
    27. {
    28. int Length = this.cilent.EndReceive(ar);
    29. if (Length == 0) { return; }
    30. string msg = Encoding.UTF8.GetString(data, 0, Length);
    31. if (GetMsg != null) GetMsg(this, msg);
    32. cilent.BeginReceive(this.data, 0, 1024, SocketFlags.None, this.ReceiveCallBack, null);
    33. }
    34. private Socket cilent;
    35. private byte[] data;
    36. private Cilent(Socket _socket) { cilent = _socket; data = new byte[1024]; }
    37. }

    食用方法:

    具体怎么使用也很简单,毕竟只开放了两个接口和一个委托,跟着我思路走应该就会用了。

    1. 首先看开放的第一个接口 SocketOn

    1. public static void SocketOn(string IP, Int32 port, int MaxListen = 100){
    2. socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    3. socket.Bind(new IPEndPoint(IPAddress.Parse(IP), port));
    4. socket.Listen(MaxListen);
    5. socket.BeginAccept(AcceptCallBack, null);
    6. }
    7. //这里的socket指的是下面的
    8. private static Socket? socket;

    因为一般来说运行一个程序只用开放一个端口就行了,所以干脆把管理Socket连入的Socket给设置成静态的,然后就是设置 地址IP,端口port,最大连接数MaxListen应该就是同时连入的最大数量吧没在这块炸过所以不太清楚。正常开放主机的127.0.0.1的80端口还是啥自己看着来就行。

    2. 再看看开放的这个委托 GetMsg

    public static Actionstring>? GetMsg;

    如果是C++的话一个函数指针就啥都啥都解决了,但是C#好像指针不大行,上网找半天找到个看起来算是靠谱的委托的实现方式。先说一下这个GetMsg是干啥的,当静态的socket经过SocketOn被打开后,会一直用异步的方式去等待一个Socket客户端连接,接到之后就会生成一个Cilent实例,这个实例一诞生就会立即异步的不断去接收客户端连入的信息,接收到消息就会执行GetMsg,其中,第一个参数就是接收到信息的Cilent对象,string就是收到的信息。

    具体使用如下(举个例子):

    1. Cilent.GetMsg = (Cilent cilent, string msg) =>
    2. {
    3. cilent.Send(msg);
    4. };

    如上就是每接收到一条消息就把消息原封不动的送回去。

    3. 所以Send这个方法应该就不用介绍了,基本是配合着GetMsg使用的,因为Cilent类的构造函数是私有的,所以没法在别的地方生成能用的Cilent对象。

    1. public void Send(string msg)
    2. {
    3. if (!cilent.Connected) return;
    4. cilent.Send(Encoding.UTF8.GetBytes(msg));
    5. }
  • 相关阅读:
    edge浏览器 路径获得
    【JavaScript面试】数组的forEach()方法总结
    计算机毕业设计(附源码)python音蕾心动
    DOM Clobbering的原理及应用
    DataX(MySQL同步数据到Doris)
    IronBarcode for .NET 2022.11.10702 Crack
    比较两个数组内容是否相同
    Chapter 14 主题模型
    MongoDB实战:应用场景以及Spring和mongodb的整合
    Vue业务组件封装(二)Form表单
  • 原文地址:https://blog.csdn.net/matrix_studio/article/details/126886125