开发环境: .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="";
//接收