代码部分(完整代码,使用方法在下面)前言:最近准备做一个多人在线小游戏的来着,因为没学过udp所以准备用以前学JavaScript时候学来的socket做一个,结果遇到bug裂开了,后来一想socket效率确实不太够然后就没修bug了,但是现在心血来潮把当时写的屎山一样的socket代码刨了一下,简单的封装了一个类。当然,是真的很简单的封装,甚至我自己都不确保能用的那种......
编译器是Microsoft Visual Studio 2022,没改过啥东西,用原生代码码的。
目前能想到但不想处理的问题直接列出来得了:
- 这种破烂异步的使用放到C++里会爆栈的不知道C#怎么说
- 客户端断连的时候估计这边接收不到断连的消息,一个巨大的bug等我有时间了修吧
- 单次收到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));
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)