C# 简单封装异步Socket Server

C# 简单封装异步Socket Server,第1张

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

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

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

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

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

public class Cilent
{
    //开放的接口部分
    public static void SocketOn(string IP, Int32 port, int MaxListen = 100)
    {
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.Bind(new IPEndPoint(IPAddress.Parse(IP), port));
        socket.Listen(MaxListen);
        socket.BeginAccept(AcceptCallBack, null);
    }
    public static Action? GetMsg;
    public void Send(string msg)
    {
        if (!cilent.Connected) return;
        cilent.Send(Encoding.UTF8.GetBytes(msg));
    }

    //不开放的部分
    private static Socket? socket;
    private static void AcceptCallBack(IAsyncResult ar)
    {
        if (socket == null) return;
        Cilent Get = new Cilent(socket.EndAccept(ar));
        Get.cilent.BeginReceive(Get.data, 0, 1024, SocketFlags.None, Get.ReceiveCallBack, null);
        socket.BeginAccept(AcceptCallBack, null);
    }
    private void ReceiveCallBack(IAsyncResult ar)
    {
        int Length = this.cilent.EndReceive(ar);
        if (Length == 0) { return; }
        string msg = Encoding.UTF8.GetString(data, 0, Length);
        if (GetMsg != null) GetMsg(this, msg);
        cilent.BeginReceive(this.data, 0, 1024, SocketFlags.None, this.ReceiveCallBack, null);
    }
    private Socket cilent;
    private byte[] data;
    private Cilent(Socket _socket) { cilent = _socket; data = new byte[1024]; }
}
食用方法:

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

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

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

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

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

public static Action? GetMsg;

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

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

Cilent.GetMsg = (Cilent cilent, string msg) =>
{
    cilent.Send(msg);
};

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

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

public void Send(string msg)
{
    if (!cilent.Connected) return;
    cilent.Send(Encoding.UTF8.GetBytes(msg));
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/2991601.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存