ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

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

2020-02-03 22:07:29  阅读:279  来源: 互联网

标签:java SOCKET 数据库 ne String Mysql new 服务端 客户端


详细课设报告以及 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,以电压为纵坐标,时间每秒为横坐标,显示电压波动状况。

动态折线图

将数据集设置函数放置在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循环依次从数组最末尾依次递减,进行数据集添加。更改后实现了动态刷新的方向更改。

Yuyao_Xu 发布了30 篇原创文章 · 获赞 1 · 访问量 4883 私信 关注

标签:java,SOCKET,数据库,ne,String,Mysql,new,服务端,客户端
来源: https://blog.csdn.net/Yuyao_Xu/article/details/104162160

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有