使用socket和mysql編寫一個簡單的物聯網服務器程序

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 測試信息錄入情況

測試方法:在上面基礎上。在分別按照協議發送狀態信息,查看數據庫是否記錄。
發送5、6號牀上傳信息
發送後數據庫狀態

4 下載

提供的代碼估計和上文的不同,下面鏈接是上學的時候爲學長代做的畢設的全套代碼,是一個實際應用,可以點擊視頻連接看到演示和講解。
嵌入式軟件|windows客戶端|服務器源碼
GITHUB 上了班之後估計很難會用到GITHUB咯

5 講解視頻

BILIBILI

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章