1 準備工作
該程序主要接收下位機發來的離牀上牀消息,並存入數據庫,達到實時監控牀位狀態的目的
1.1 開發環境
使用了java語言,平臺是eclipse,JDK版本:1.7.0_13,數據庫使用mysql,需要向程序中導入mysql-connector-java-5.1.28-bin.jar的驅動包
1.2 數據庫建立
表名:RY
設計:
1.3 協議
發送在監測變化時
包頭 | 牀位 | 狀態 | 保留 |
---|---|---|---|
0xAAAA | 一個字節 | 一個字節 | 一個字節0XFF |
狀態:
命令字 | 說明 |
---|---|
0x01 | 上牀 |
0x02 | 離牀 |
2 代碼簡述
2.1 socket部分
serversocket.java 程序入口
public class ServerSocket {
public static void main(String[] args) {
new ServerListener().start(); //建立實時監聽客服端
}
由於socket會阻塞進程,如果直接寫在主線程中,程序就只能執行socket的功能,使用我另外開啓一個線程,單獨用來通信。
ServerListener.java
public class ServerListener extends Thread{
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(9999); //端口
while(true){
//每當有一個客服端連接就有一個socket
Socket socket = serverSocket.accept();//阻塞
System.out.println("有客服端鏈接-------");
ReceiveSocket cs = new ReceiveSocket(socket);//新線程
cs.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
這裏每連接一個客服端,就想控制檯輸出一個消息,並又建立一個線程單獨對其處理。
ReceiveSocket.java 消息接收與處理
public class ReceiveSocket extends Thread{
Socket socket;
int getCounter = 0; //定義接收到的數據大小
int bedNumber = 0; //牀位
int state = 0 ; //狀態
public ReceiveSocket(Socket s){
this.socket = s;
}
public void run()
{
try {
boolean connect = true; //連接成功了的
byte getData[] = new byte[5];
//包頭(2)+牀位(1)+狀態(1)+保留(1) = 5個字節
InputStream isTemplet = null;
OutputStream osTemplet = null;
while(true)
{
try {
osTemplet = socket.getOutputStream();
isTemplet = socket.getInputStream();
} catch (Exception e) {
connect = false ;
System.out.println("Broken A");
break;
}
if(socket.isConnected()) //判斷是否在連接中
{
try
{
getCounter=isTemplet.read(getData, 0, 5);
}
catch(IOException e)
{
e.printStackTrace();
System.out.println("Broken B");
connect = false;
break;
}
}
//存入數據庫
//System.out.println(getCounter); //打印出接收到的數據個數
if(getData[0] == -86 && getData[1] == -86) //0xaa就是-86
{
bedNumber =getData[2];//得到牀位數
state = getData[3];//得到狀態值
System.out.println(bedNumber);
System.out.println(state);
DB_Connection a =new DB_Connection(bedNumber,state);
getData[0] == 0; //防止多次進入
}
}
} catch (Exception e) {
e.printStackTrace();//在命令行打印異常信息在程序中出錯的位置及原因
}
}
}
這裏循環監聽,按照協議每次取出5個字節數據,解析後存入數據庫
2.2 數據庫部分
DB_Connection.java 數據庫操作
public class DB_Connection {
String Connection="jdbc:mysql://localhost:3306/RY?"+
"user=root&password=&characterEncoding=UTF8";
String uri = "jdbc:mysql://localhost:3306/RY?";
String user = "user=root&password=&characterEncoding=UTF8";
String connet = "jdbc:mysql://xxx.xxx.xxx.xxx:3306/RY?"
+ "user=root&password=&useUnicode=true&characterEncoding=UTF8";
String inSql = null;
public DB_Connection(int bedNumber,int state)
{
java.sql.Connection conn = null;
java.sql.Statement stmt =null;
//註冊驅動
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("Broken driver");
e.printStackTrace();
}
//創建連接
try {
conn = DriverManager.getConnection(connet);
//獲取表達式
stmt= conn.createStatement();
} catch (SQLException e) {
System.out.println("Broken conn");
e.printStackTrace();
}
Date date = new Date();//獲得系統時間.
String nowTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);//將時間格式轉換成符合Timestamp要求的格式.
Timestamp goodsC_date = Timestamp.valueOf(nowTime);//把時間轉換
if(state ==1)
inSql = "insert into message(bed_Number,state,Dtime) values('" + bedNumber + "','back','" + goodsC_date + "')";
else {
inSql = "insert into message(bed_Number,state,Dtime) values('" + bedNumber + "','leave','" + goodsC_date + "')";
}
try {
stmt.executeUpdate(inSql);
} catch (SQLException e) {
System.out.println("Broken insert");
e.printStackTrace();
}
try {
stmt.close();
conn.close();
} catch (SQLException e) {
System.out.println("Broken close");
e.printStackTrace();
}
}
}
一開始的字符串是用來定義連接數據庫的,那些xxx就是ip地址,3306就是默認數據庫的端口,RY就是表明
我這裏的構造函數是直接傳入了兩個需要得到的消息,並簡單判斷一下,按照格式存入數據庫。
3 測試
3.1 測試多客服端連接情況
測試方法:開啓兩個網絡調試助手,運行服務器端程序。使用網絡調試助手連接服務器,查看情況,
3.2 測試信息錄入情況
測試方法:在上面基礎上。在分別按照協議發送狀態信息,查看數據庫是否記錄。
4 下載
提供的代碼估計和上文的不同,下面鏈接是上學的時候爲學長代做的畢設的全套代碼,是一個實際應用,可以點擊視頻連接看到演示和講解。
嵌入式軟件|windows客戶端|服務器源碼
GITHUB 上了班之後估計很難會用到GITHUB咯