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];
string dataBack = Encoding.ASCII.GetString(bytes,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,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("宋體",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.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.getTime().split(" ")[1]);
}
先用size()獲取陣列大小,再以for迴圈依次從陣列最末尾依次遞減,進行資料集新增。更改後實現了動態重新整理的方向更改。