基于SocketAsyncEventArgs(IOCP)的高性能TCP服务器实现(二)——服务端信息接收窗体实现(C#)

基于SocketAsyncEventArgs(IOCP)的高性能TCP服务器实现(一)——封装SocketAsyncEventArgs这篇文章中,我们首先用自定义的类SocketServer封装了SocketAsyncEventArgs,封装完之后,我们可以创建一个Windows窗体来实现,接收客户端的信息,并且显示并处理,下面简单介绍下我是如何用C#来实现这个窗体的,中间有不足之处请大家指出来,多谢。

首先看下我实现的界面,如下图所示,界面其实很简单,一个服务器IP,还有一个连接端口(可以自定义),另外就是我们可以自定义客户端数量,我这里默认是100,我最高测试了一万个客户端的情况。后面跟大家聊聊模拟的情况。有一定C#基础的朋友这个界面肯定三两下就做好了,那我们就详细讲讲怎么用封装了SocketAsyncEventArgs的自定义的类SocketServer来实现信息接收的。

第一步,需要在窗体的代码文件中定义变量:

        private SocketServer _socketServer;//封装好SocketAsyncEventArgs的自定义类
        private int msgCount = 0;//接收到信息的条数计数器
        private bool Break=false;//服务停止的标志

上述代码中,_socketServer是我们已经封装好SocketAsyncEventArgs的自定义类,其实就是一个通讯服务端,他可以启动停止服务并接收客户端的信息。“Break”是当用户点击“停止服务”时,设置的一个标志。运行过程中监测到“Break”为True,则服务停止。

第二步,就是启动服务,读者请注意,启动服务之前,请自行把窗体中的参数在代码中,转化为相应的变量赋值给_socketServer。如一下代码所示:

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            try
            {
                _socketServer = new SocketServer(10000, 200);
                _socketServer.Init();
                _socketServer.ReceiveClientData += onReceiveData;
                _socketServer.Start(new IPEndPoint(serverIP, serverPort));
                tsslState.Text = "服务已启动";
             }
             catch (Exception ex)
             {
                MessageBox.Show(ex.Message);
             }
        }

在上述代码中,我们首先把通过构造函数将_socketServer定义,第一个参数表示最大连接数,第二个参数表示每一条信息的容量,单位是Kb。然后通过_socketServer.Init();进行初始化,接着注册信息接收到的处理函数:_socketServer.ReceiveClientData += onReceiveData;,最后启动服务,参数是服务器的IP地址和端口。

第三步,就是接收信息并处理。在第二步中,我们已经注册了信息处理函数onReceiveData,具体实现代码如下:

        private void onReceiveData(AsyncUserToken token, byte[] buff)
        {
            string s = byteToHexStr(buff);
            msgCount++;
            if (!Break)
            {
                new Thread((ThreadStart)(delegate ()
                {
                    // 此处警惕值类型装箱造成的"性能陷阱"
                    listView1.Invoke((MethodInvoker)delegate ()
                    {
                        ListViewItem lviItem = new ListViewItem();
                        ListViewItem.ListViewSubItem lviSubItem;
                        lviItem.Text = msgCount.ToString();

                        lviSubItem = new ListViewItem.ListViewSubItem();
                        lviSubItem.Text = s;
                        lviItem.SubItems.Add(lviSubItem);


                        listView1.Items.Add(lviItem);
                    });
                    tsslMessageCount.Text = "共接收到消息:"+msgCount.ToString()+"条";
                }))
                .Start();
            }
            else return;
        }

上述代码是onReceiveData,只要服务器接收到信息,就是转入这个函数,我这里只是简单的把数据转为字符串并显示在ListView中,读者也可以在这个函数中将信息进行解析并入库,这方面读者就自行处理。

第四步,就是如果我们终止服务,希望有一个优雅的解决,并且要告知客户端我们的服务停止了。如下代码:

        private void btnStopServer_Click(object sender, EventArgs e)
        {
            _socketServer.Stop();
            Break = true;
            tsslState.Text = "服务已停止";
            MessageBox.Show("停止服务,共接收到信息"+msgCount.ToString()+"条");
        }

这里首先通过_socketServer.Stop()停止了所有客户端的Socket连接,然后把Break设置为True,停止主线程我们停止服务了,ListView不需要再添加数据了。

窗体实现的代码:https://download.csdn.net/download/aplsc/11824454

C#中,IO Completion Ports (IOCP) 是一种高级异步I/O模型,它允许服务器高效地处理大量并发连接。通过IOCP,TCP服务器可以利用非阻塞I/O技术,将数据接收、处理和发送的工作分散到多个线程或工作队列上,提高了性能和响应能力。 要在C#中使用IOCP实现TCPServer,你需要做以下步骤: 1. **创建IOCompletionPort**: 首先,你需要创建一个`IOCompletionPort`实例,这是所有操作的核心。 ```csharp using System.IO.Ports; using Microsoft.Win32.SafeHandles; using NativeIO = System.Runtime.InteropServices.Marshal; IOCompletionPort completionPort = new IOCompletionPort(new SafeFileHandle(INVALID_HANDLE_VALUE, Ownership.Duplicate), IntPtr.Zero); ``` 2. **注册接收回调**: 你需要设置一个回调函数,当有新的数据到达时,这个函数会被调用。 ```csharp NativeIO.AddRef(kernel32.GetQueueOverlappedCompletionPort(completionPort.Handle)); completionPort.RegisterWaitForSingleObject(socket.ReceiveOverlapped, NativeIO.WAIT_IO_COMPLETION, ref overlapped, -1, true); ``` 3. **监听并接受连接**: 使用`AcceptAsync`方法创建一个新的Socket,并将其关联到IOCP。 ```csharp Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); await serverSocket.AcceptAsync(socketAsyncEventArgs); socketAsyncEventArgs.SetEvent(); ``` 4. **处理接收数据**: 当接收到数据后,会触发你的回调函数,在这里你可以读取数据并处理请求。 5. **清理和释放资源**: 当完成操作后,记得从IOCP中删除等待事件,并清理相关的网络资源。 ```csharp socket.Close(); NativeIO.ReleaseWaitHandle(overlapped.hEvent); NativeIO.PostQueuedCompletionStatus(completionPort.Handle, 0, IntPtr.Zero, overlapped); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值