[朝花夕拾]基于C#的模拟仿真平台设计(部分)及服务器异步通信代码

开发环境: .net 4.5

开发语言: C#

平台架构:C-S架构

数据库: MariaDB

插件:Ribbon UI、DotNetBar

一,服务器端总体设计

根据项目需求将平台设计分为以下模块:

a)        显示信息模块

b)        用户信息管理模块

c)        配置模块

d)        与客户端通信模块

e)        数据库模块

f)         结果处理模块

g)        仿真软件控制模块

二,服务器端架构

服务器端由于两种仿真软件对操作系统的不同要求,和文件管理和数据安全方面的考虑,故使用三个服务器端,其中两个作为计算服务器,另一个作为存储服务器使用。

三,与客户端通信模块

本项目使用异步通信模式,并制定了一套通信方案,发送的信息使用UTF-8编码格式:

a)        通信内容开始符(2byte):##,识别通信内容开始

b)        通信内容大小(4byte):构造完成正文部分后填写数据包大小的int数值以验证传输数据是否正确

c)        通信内容结束符(2byte):$$,识别通信内容结束

d)        通信内容正文(不定,构造完成后确定长度)

e)        通信内容形式:命令|参数|参数|….其中参数的个数以及含义依据命令的不同来构造生成。

四,仿真软件控制模块

当客户端发出了执行仿真软件的命令时,服务器:

a)        开启一个子线程(守护线程,在服务端版Socket编程需要处理长时间没有发送数据的Socket,需要在超时多长时间后断开连接,我们需要独立一个线程(DaemonThread)来轮询,在执行断开时,需要把Socket对象锁定,并调用CloseClientSocket来断开连接)来负责处理仿真软件脚本,并将信息添加到数据库中。

b)        分别执行发送过来的几个脚本,并使用子线程监控脚本运行状态。

c)        当执行成功后将脚本文件、结果文件等相关文件上传到存储服务器,并更新数据库。

对于不能并发执行的仿真软件,设置一个脚本对象的队列。当执行脚本空闲并且队列中有脚本时,弹出第一个脚本进行执行。

五,异步通信模块代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Windows.Forms;
using System.Threading;
using System.Data;
using System.IO;

namespace server2014
{
    public class SocketServer
    {

        public static string msgstr = "                     ";
        // Thread signal.
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        public SocketServer()
        {
            //初始化SOCKET实例
            ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            //初始化终结点实例
            localEP = new IPEndPoint(IPAddress.Any, setPort);
        }
        //监听网络连接的socket
        public Socket ListenSocket = null;
        //监听端口
        public int localPort = 9999;
        //监听节点
        public IPEndPoint localEP = null;
        //进行网络监听的线程
        public Thread ListeningThread = null;
        //SOCKET,用于等待其它客户端的连接
        Socket server = null;
        //负责与客户端进行通信的socket
        Socket ClientSocket = null;

        //用来设置服务端监听的端口号
        public int setPort
        {
            get { return localPort; }
            set { localPort = value; }
        }
        //新建线程,进行网络监听
        public void startListenThread()
        {
            //新建一个委托线程
            ThreadStart myThreadDelegate = new ThreadStart(Listen);
            //实例化新线程
            ListeningThread = new Thread(myThreadDelegate);
            ListeningThread.IsBackground = true;
            ListeningThread.Start();
        }
        //终止监听线程
        public void stopListenThread()
        {
   
            if (ListeningThread != null)
            {
 
                ListeningThread.Abort();
            }
        }
        //监听函数
        private void Listen()
        {

            setPort = 9999;
            try
            {
                //绑定
                ListenSocket.Bind(localEP);
                //监听
                ListenSocket.Listen(10);
                //开始接受异步连接
                ListenSocket.BeginAccept(new AsyncCallback(OnConnectRequest), ListenSocket);
            }
            catch (Exception e)
            {
                MessageBox.Show("开启监听服务失败!\n失败原因:" + e.Message);
                Users.writeLog(MainForm.dailylogPath, DateTime.Now.ToString() + " 端口" + localPort + " 开启监听服务失败");
            }
        }
        //当有客户端连接时的处理
        public void OnConnectRequest(IAsyncResult ar)
        {
            string ip ="";
            string ipmsgstr="";
            //接收的客户端传送过来的数据
            byte[] receiveData = new byte[1024];
            byte[] senddata = null;
            try
            {
                //初始化一个SOCKET,用于等待其它客户端的连接
                server = (Socket)ar.AsyncState;
                server.BeginAccept(new AsyncCallback(OnConnectRequest), server);
                //负责与客户端进行通信的socket
                ClientSocket = server.EndAccept(ar);
                //获取客户端的IP和端口
                ip = ClientSocket.RemoteEndPoint.ToString();
                ipmsgstr = ip + "                           ";
            }
            catch
            {
                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + "\r\n");
            }
            //负责接收客户端信息
            while (true)
            {
                int recv = 0;
                try
                {
                    recv = ClientSocket.Receive(receiveData);
                    //对传输过来的数据进行解析
                    byte[] effemsg = Protocol.SubByteArray(receiveData, 0, recv);
                    string[] parameters = Protocol.anaMsg(effemsg);
                    int per = 0;//判断权限
                    int[] perpass = { 0, 0 };
                    //根据协议命令的不同进行不同的处理
                    switch (parameters[0])
                    {
                        case "-1":
                            //协议解析出错,断开连接
                            try
                            {
                                //断开连接
                                ClientSocket.Disconnect(true);
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "与客户端断开连接! " + "\r\n");
                                return;
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + "\r\n");
                                return;
                            }
                        case "0":
                            //查看服务器端执行的所有任务
                            perpass = Business.check(parameters[1], parameters[2]);
                            per = perpass[1];
                            if (perpass[0] > 0)
                            {
                                //用户名密码验证成功则添加用户
                                //Business.addUser(parameters[1], parameters[2]);
                                Business.loginUser(parameters[1], parameters[2]);
                                string sendstring = Business.getAllTasks();
                                senddata = Protocol.getLookReturnMsg(sendstring);
                                try
                                {
                                    MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "查看服务器运行状况。" + "\r\n");
                                    ClientSocket.Send(senddata);
                                }
                                catch (Exception e)
                                {
                                    MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + e.Message + "\r\n");
                                }
                            }
                            else
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "查看服务器运行状况时密码验证失败!" + "\r\n");
                                senddata = Protocol.getCheckReturnMsg(parameters[1], per.ToString(), false);
                                try
                                {
                                    ClientSocket.Send(senddata);
                                }
                                catch (Exception e)
                                {
                                    MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + e.Message + "\r\n");
                                }
                            }
                            break;
                        case "1":
                            //验证客户端用户名密码
                            perpass = Business.check(parameters[1], parameters[2]);
                            per = perpass[1];
                            if (perpass[0] > 0)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "登录成功!" + "\r\n");
                                Users.writeLog(MainForm.dailylogPath, DateTime.Now.ToString() + " " + ip + " 用户 " + parameters[1] + " 登录成功!");
                                LoginForm.users.ftpupdown.MakeDir(parameters[1]);
                                //用户名密码验证成功则添加用户
                                //Business.addLoginUser(parameters[1]);
                                //Business.addUser(parameters[1], parameters[2]);
                                Business.loginUser(parameters[1], parameters[2]);
                                string serveru = Config.getparameter("Serveru");
                                string ansysPath = Config.getparameter("ansysProgramPath");
                                DatabaseTools db = Users.databaseTools4;
                                List tasklist = new List();
                                string userpath = Users.ftpServerpath + "\\" + parameters[1];
                                Users.creatDirtionary(userpath);
                                db.queryTaskByUsername(parameters[1], tasklist);
                                foreach (string taskname in tasklist)
                                {
                                    string taskpath = userpath + "\\" + taskname;
                                    Users.creatDirtionary(taskpath);
                                    for (int i = 1; i < 4; i++)
                                    {
                                        //i为脚本类型
                                        string kindpath = taskpath + "\\" + Users.scriptKindTrans(i);
                                        Users.creatDirtionary(kindpath);
                                        List scriptsList = new List();
                                        Users.databaseTools.queryScriptByUserTaskname(parameters[1], taskname, i, 3, scriptsList);
                                        foreach (string scriptname in scriptsList)
                                        {
                                            string scriptpath = kindpath + "\\" + scriptname;
                                            Users.creatDirtionary(scriptpath);
                                            string sciptfilepath = scriptpath + "\\script";
                                            Users.creatDirtionary(sciptfilepath);
                                            string scipttemppath = scriptpath + "\\temp";
                                            Users.creatDirtionary(scipttemppath);
                                            string sciptresultpath = scriptpath + "\\result";
                                            Users.creatDirtionary(sciptresultpath);
                                        }
                                    }
                                }
                                List taskAndUpdateList = new List();
                                db.queryTaskAndUpdateByUsername(parameters[1], taskAndUpdateList);
                                senddata = Protocol.getLoginCheckReturnMsg(parameters[1], serveru,ansysPath, taskAndUpdateList, per.ToString(), true);
                                //将客户端查询时间记录到txt文本中
                                foreach (string taskname in tasklist)
                                {
                                    string taskpath = userpath + "\\" + taskname;
                                    Users.writeClientLogin(taskpath + "\\taskLastQuery.txt", DateTime.Now.ToString());
                                }
                                try
                                {
                                    ClientSocket.Send(senddata);
                                }
                                catch (Exception e)
                                {
                                    MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + e.Message + "\r\n");
                                }
                            }
                            else
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "登录失败!" + "\r\n");
                                //senddata = Protocol.getCheckReturnMsg(parameters[1], per.ToString(),false);
                                senddata = Protocol.getLoginCheckReturnMsg(parameters[1], "","", new List(), per.ToString(), false);
                                try
                                {
                                    ClientSocket.Send(senddata);
                                }
                                catch (Exception e)
                                {
                                    MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + e.Message + "\r\n");
                                }
                            }
                            break;
                        case "2":
                            //添加新的脚本并且执行
                            Business.loginUser(parameters[1], parameters[2]);
                            MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "执行任务" + parameters[3] + "的脚本程序" + parameters[4] + "\r\n");
                            try
                            {
                                //将新的任务保存到USERS中
                                LoginForm.users.addTask(parameters[1], parameters[3]);
                                LoginForm.users.addScript(parameters[1], parameters[3], parameters[4], int.Parse(parameters[5]));
                                //执行新的任务,执行脚本
                                //------------------------------------------------------------------
                                bool executeflag = false; //执行是否成功
                                //执行脚本的总次数
                                int projectcount = int.Parse(parameters[6]); 
                                //当前执行脚本的数量
                                int projecttemp = 0;
                                if (int.Parse(parameters[5]) == 2)
                                {
                                    Users.databaseTools.updateScriptState(parameters[1], parameters[3], parameters[4], 2);
                                    string xmlpath = Users.ftpServerpath + "\\" + parameters[1] + "\\" + parameters[3] + "\\test\\" + parameters[4] + "\\" + parameters[4] + ".xml";
                                    string curxmlpath = Users.ftpServerpath + "\\" + parameters[1] + "\\" + parameters[3] + "\\test\\" + parameters[4] + "\\temp\\" + parameters[4] + ".xml";
                                    File.Copy(curxmlpath, xmlpath, true);
                                    for (; projecttemp < projectcount; projecttemp++)
                                    {
                                        executeflag = Business.executeScript(parameters[1], parameters[3], parameters[4], int.Parse(parameters[5]), projecttemp, projectcount);
                                        Thread.CurrentThread.Join(1000);
                                    }
                                }
                                else if (int.Parse(parameters[5]) == 1)
                                {
                                    executeflag = Business.executeScript(parameters[1], parameters[3], parameters[4], int.Parse(parameters[5]), projecttemp, projectcount);
                                }
                                else if (int.Parse(parameters[5]) == 3)
                                {
                                    executeflag = Business.executeScript(parameters[1], parameters[3], parameters[4], int.Parse(parameters[5]), projecttemp, projectcount);
                                    //更改脚本状态为运行
                                    Users.databaseTools.updateScriptState(parameters[1], parameters[3], parameters[4], 2);
                                }
                                //------------------------------------------------------------------
                                //bool executeflag = Business.executeScript(parameters[1], parameters[3], parameters[4], int.Parse(parameters[5]));
                                //Users.checkAddsettings();
                                senddata = Protocol.getExecuteReturnMsg(parameters[1], parameters[3], parameters[4], executeflag);
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "执行任务" + parameters[3] + "的脚本程序" + parameters[4] + "错误!\r\n");
                            }
                            try
                            {
                                ClientSocket.Send(senddata);
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + e.Message + "\r\n");
                            }
                            break;
                        case "3":
                            //查询某一任务中某一个脚本的状态
                            Business.loginUser(parameters[1], parameters[2]);
                            //查询任务下某一脚本状态
                            MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "查询任务" + parameters[3] + "的脚本程序" + parameters[4] + "的执行状态。\r\n");
                            //查询任务之中某一个脚本的状态
                            scriptStates scriptstate = LoginForm.users.queryScriptState(parameters[1], parameters[3], parameters[4], int.Parse(parameters[5]));
                            //返回任务状态
                            senddata = Protocol.getQueryReturnMsg(parameters[1], parameters[3], parameters[4], scriptstate.ToString(), parameters[5]);
                            try
                            {
                                ClientSocket.Send(senddata);
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + e.Message + "\r\n");
                            }
                            break;
                        case "4":
                            //删除某一任务的执行
                            Business.loginUser(parameters[1], parameters[2]);
                            //删除任务
                            int deleteflag = Users.databaseTools4.deleteTask(parameters[1], parameters[2]);
                            if (deleteflag > 0)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "删除任务" + parameters[2] + "成功。\r\n");
                            }
                            else
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "删除任务" + parameters[2] + "失败。\r\n");
                            }
                            //返回任务状态
                            senddata = Protocol.getTdeleteReturnMsg(parameters[1], parameters[2], deleteflag.ToString());
                            try
                            {
                                ClientSocket.Send(senddata);
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + "\r\n");
                            }

                            break;

                        case "5":
                            Business.loginUser(parameters[1], parameters[2]);
                            MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "查询任务" + parameters[3] + "下脚本信息。\r\n");
                            //任务
                            DataTable dt1 = Users.queryScriptMessage(parameters[1], parameters[3], new string[] { "scriptname", "scriptkind", "scriptstate" });
                            bool queryTaskFlag = true;
                            //返回任务状态
                            senddata = Protocol.getQueryTaskReturnMsg(parameters[1], parameters[3], dt1, queryTaskFlag);
                            try
                            {
                                ClientSocket.Send(senddata);
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + "\r\n");
                            }
                            break;
                        case "6":
                            if (int.Parse(parameters[1]) == 1)
                            {
                                Users.databaseTools4.addMaterial(parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10], parameters[11], parameters[12], parameters[13], parameters[14], parameters[15], parameters[16], parameters[17], parameters[18], parameters[19], parameters[20]);
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "添加材料" + parameters[3] + "。\r\n");
                            }
                            else if (int.Parse(parameters[1]) == 2)
                            {
                                Users.databaseTools4.deleteMaterial(parameters[2]);
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "删除材料" + parameters[2] + "。\r\n");
                            }
                            else if (int.Parse(parameters[1]) == 3)
                            {
                                Users.databaseTools4.updateMaterial(parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10], parameters[11], parameters[12], parameters[13], parameters[14], parameters[15], parameters[16], parameters[17], parameters[18], parameters[19], parameters[20]);
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "修改材料" + parameters[3] + "。\r\n");
                            }
                            else if (int.Parse(parameters[1]) == 4)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "用户" + parameters[1] + "查询材料。\r\n");
                            }
                            DataTable dt = new DataTable();
                            Users.databaseTools4.queryMaterial(0 + "", dt);
                            //dt.Rows[0][1];
                            senddata = Protocol.getMaterialReturnMsg(dt);
                            try
                            {
                                ClientSocket.Send(senddata);
                            }
                            catch (Exception e)
                            {
                                MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误!" + "\r\n");
                            }
                            break;
                    }
                }
                catch (SocketException e)
                {
                    MainForm.mainfrm.messageShow(DateTime.Now.ToString() + msgstr + ipmsgstr + "网络错误! " + "\r\n");
                    return;
                }
                finally
                {

                }
            }
        }
    }
}

你可能感兴趣的:(C#)