SOCKET编写客户端和服务端通信,连接Mysql数据库,java实现动态监控

详细课设报告以及 C#、java 源码见
码云: https://gitee.com/xyy9/socket
github: https://github.com/XYYhub/socket
建立数据库略过

C#连接数据库

需要添加MySql.Data.dll引用连接数据库
代码页添加using MySql.Data.MySqlClient

string str = "server=localhost; User Id=root; password=root; Database=server";
//连接MySQL的字符串
MySqlConnection mycon = new MySqlConnection(str);//实例化链接
mycon.Open();//开启连接
MySqlCommand mycmd = new MySqlCommand("insert into tcp(type,id,sn,power,state,time) values('" + type1 + "','" + id1 + "','" + sn1 + "','" + power1 + "','" + state1 + "','" + time1 + "')", mycon);
if (mycmd.ExecuteNonQuery() > 0)
{
    Console.WriteLine("数据插入成功!");
}
 mycon.Close();//关闭

服务端和客户端的双向通信

服务端和客户端的双向通信,在基于服务端接收完客户端的信息后,需要向客户端发送反馈信息,以告知客户端,信息已经成功被接收,建立此反向通信机制后,也可通过从服务端发送相关控制信息给客户端,来对客户端进行相关操作。

服务端发送简单反馈信息

在服务端接收完毕客户端数据,并将数据存入数据库成功后。服务端开始发送反馈信息
1、服务端发送:
byte[] dataToC = System.Text.Encoding.ASCII.GetBytes(“Received successfully”);
handler.Send(dataToC);

2、客户端接收:
byte[] bytes = new Byte[1024];
int bytesRec = clientSocket.Receive(bytes);
string dataBack = Encoding.ASCII.GetString(bytes, 0, bytesRec);
Console.WriteLine(dataBack);
就此即可完成服务端的自定义语句,在客户端接收并显示。

3.设计思想:
在服务端建立控制开关机制,以判断向客户端传输的具体反馈信息,客户端根据收到的反馈信息判断具体的执行任务。

服务端控制函数:
初步采用命令台内,键盘输入进行控制,在每一次循环建立端口监听时,都进行对键盘的监听,键盘输入相应的终止按键,则switch语句便执行相应的终止语句,否则默认跳出判断语句。以下为相应代码。

//非阻塞式监听键盘输入
if (Console.KeyAvailable)
{
    ConsoleKeyInfo key = Console.ReadKey(true);
    switch (key.Key)
    {
        case ConsoleKey.F2:
            Console.WriteLine("You pressed F2!");
            byte[] data = System.Text.Encoding.ASCII.GetBytes("ShutDown");
            handler.Send(data);
            break;
        default:
            break;
    }
}
客户端判断函数:
if (dataBack == "ShutDown")
{
    clientSocket.Close();
}

进一步优化:
为便于连接GUI控制,应将判断内容改为具体的某一个变量,而非对键盘输入的监听,在服务端与客户端都应以语句中的state的值为“on”或“off”来控制客户端的状态。

利用JAVA和MySQL实现数据的动态实时监控

设计思想:在服务端分割信息存入数据库后,用JAVA连接数据库,运用JfreeChart实现设备电压变化的可视化以及动态更新。
主要步骤如下:

设计DBUtil工具类模块。

用于连接Mysql数据库。
主要代码如下:

Connection conn = null;
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/server?serverTimezone=UTC";
			String username = "root";
			String password = "******";
			conn = DriverManager.getConnection(url,username,password);

并包裹try/catch异常获取,打印错误提示以及错误信息。

设计Entity模块,

用于创造存储Mysql中每条数据的类,并构造get函数用于获取确定信息,构造set函数用于设定或者修改具体信息。
类内的具体属性值如以下代码,一一对应于信息传递中规定的信息格式,即数据库中的数据格式,全部定义为String字符串类型。为了避免外部的随意干涉,设定为private私有属性。

public class Entity {
	private String type;
	private String id;
	private String sn;
	private String power;
	public String state;
	private String time;
为了方便对类内的属性进行获取和设定,需要对每个属性都构造get以及set函数,以下为Type属性的get以及set函数,其余省略,不再赘述。
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
		}
		…………
}

设计DAO模块

用于构造各类与数据库相关的功能函数,比如getAll() 获取数据库中的全部数据,getTen() 获取数据库中最新的十条数据,以及update() 修改函数,用于修改数据库中的某条数据。
以下为主要源代码,因为获取的结果为多个类,所以设定获取函数的类型为java中的ArrayList数组链表,此函数既拥有数组的特性,也拥有链表的特性,极为方便。

	public ArrayList<Entity> getAll(){
		ArrayList<Entity> ar = new ArrayList<Entity>();

设定conn调用DBUtil中的连接数据库函数,ps为执行语句函数,rs为结果存放函数。

		Connection conn = DBUtil.getConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
设定sql语句如下,并执行,且存放执行结果。
		String sql = "select type,id,sn,power,state,time from tcp";
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();

以while循环不断调用Entity中的set函数,保存获取的数据库信息至新建的ArrayList类中。

			while(rs.next()) {
				Entity ent = new Entity();
				ent.setType(rs.getString("type"));
				ent.setId(rs.getString("id"));
				ent.setSn(rs.getString("sn"));
				ent.setPower(rs.getString("power"));
				ent.setState(rs.getString("state"));
				ent.setTime(rs.getString("time"));
				ar.add(ent);
			}

至此数据全部保存在ArrayList ar中。最后return ar函数即可获得结果。需要注意的是一定要记得释放rs、ps、conn三个函数,并且注意要依次释放。
将SQL语句改为

"select * from tcp Order By time Desc limit 10"

即可编写获取最新的十个数据的功能函数 getTen(),为了给gui控制界面做准备,也写了一个修改函数update,用以从java更改数据库中的某个ID的设备的状态,以进行开启和关闭操作,具体仍有待实现,此为java数据库接口,主要源码如下:

String sql = "UPDATE tcp SET state= ? WHERE id=?";
			ps = conn.prepareStatement(sql);
			ps.setString(1, ent.getState());

设计Charts模块

用于将数据通过JfreeChart实现数据库中的信息可视化,绘制成折线图显示近十条数据的变化趋势。并构造定时器,实现每隔一秒动态刷新,重新获取最新的十条数据库内数据。
JFreeChart是JAVA平台上的一个开放的图表绘制类库。它完全使用JAVA语言编写,是为applications, applets, servlets 以及JSP等使用所设计。JFreeChart可生成饼图(pie charts)、柱状图(bar charts)、散点图(scatter plots)、时序图(time series)、甘特图(Gantt charts)等等多种图表,并且可以产生PNG和JPEG格式的输出。
本次我们使用它的折线图绘制。要使用JfreeChart需要官网下载Jcommon以及JfreeChart两个包,目前最新的包为jcommon-1.0.23.jar以及jfreechart-1.0.19.jar下载完毕后导入工程,并构造路径,即可使用JfreeChart。

通过StandardChartTheme 可以设置Chart的外观格式,如字体大小等。

StandardChartTheme mChartTheme = new StandardChartTheme("CN");
        mChartTheme.setLargeFont(new Font("黑体", Font.BOLD, 20));
        mChartTheme.setExtraLargeFont(new Font("宋体", Font.PLAIN, 15));
    mChartTheme.setRegularFont(new Font("宋体", Font.PLAIN, 15));

通过for循环依次设定折线图的数据集。

ArrayList<Entity> ar=new DAO().getTen();
        int index = ar.size()-1;
		for(Entity ne; index>=0 ;index--) {
			ne = ar.get(index);
			mDataset.addValue(Double.valueOf(ne.getPower()), "设备"+ne.getId(), ne.getTime().split(" ")[1]);
		}

新建折线图,设定表标题及x轴y轴及其他相关信息。

JFreeChart mChart = ChartFactory.createLineChart(
                "电压波动折线图",//图名字
                "时间",//横坐标
                "电压",//纵坐标
                mDataset,//数据集
                PlotOrientation.VERTICAL,
                true, // 显示图例
                true, // 采用标准生成器
            false);// 是否生成超链接

最终实现以下画面4.22,以电压为纵坐标,时间每秒为横坐标,显示电压波动状况。

SOCKET编写客户端和服务端通信,连接Mysql数据库,java实现动态监控

将数据集设置函数放置在while无限循环中,并设置线程休眠1000ms,以实现每秒动态更新折线图。

while(true){
    mPlot.setDataset(GetDataset());
Thread.sleep(1000);
	}

遇到的问题

在动态实现java折线图显示最新的十条数据的时候,由于SQL语句为
select * from tcp Order By time Desc limit 10
即将数据按时间顺序倒序排序,并输出前十个,这导致了越新的数据会保存在数组的越前面,使输出绘制折线图的时候,最新的数据显示在了折线图的左侧,整个折线图动态更新时,会整体从左向右移动,这不符合传统的用户使用逻辑,所以需要对从数据库中提取出的数据,在赋值给折线图数据集时,进行逆序操作。具体更改如下:

原代码:

ArrayList<Entity> ar=new DAO().getTen();
		for(Entity ne:ar) {
mDataset.addValue(Double.valueOf(ne.getPower()), "设备"+ne.getId(), ne.getTime().split(" ")[1]);
}

更改后代码:

ArrayList<Entity> ar=new DAO().getTen();
        int index = ar.size()-1;
		for(Entity ne; index>=0 ;index--) {
			ne = ar.get(index);
mDataset.addValue(Double.valueOf(ne.getPower()), "设备"+ne.getId(), ne.getTime().split(" ")[1]);
		}

先用size()获取数组大小,再以for循环依次从数组最末尾依次递减,进行数据集添加。更改后实现了动态刷新的方向更改。

SOCKET编写客户端和服务端通信,连接Mysql数据库,java实现动态监控SOCKET编写客户端和服务端通信,连接Mysql数据库,java实现动态监控 Yuyao_Xu 发布了30 篇原创文章 · 获赞 1 · 访问量 4883 私信 关注
上一篇:磨刀不误砍柴工——统一日志系统 Log4Net/ExceptionLess


下一篇:Python learning by case study@[April] (跟着April用真实案例学Python) Lesson six “for loop”循环