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

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

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

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

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

        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

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