1 准备工作

该程序主要接收下位机发来的离床上床消息,并存入数据库,达到实时监控床位状态的目的

1.1 开发环境

使用了java语言,平台是eclipse,JDK版本:1.7.0_13,数据库使用mysql,需要向程序中导入mysql-connector-java-5.1.28-bin.jar的驱动包

1.2 数据库建立

表名:RY

设计:

java 物联网通讯服务器 基于socket的物联网服务器_eclipse

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 测试多客服端连接情况

测试方法:开启两个网络调试助手,运行服务器端程序。使用网络调试助手连接服务器,查看情况,

java 物联网通讯服务器 基于socket的物联网服务器_eclipse_02

3.2 测试信息录入情况

测试方法:在上面基础上。在分别按照协议发送状态信息,查看数据库是否记录。

java 物联网通讯服务器 基于socket的物联网服务器_mysql_03


java 物联网通讯服务器 基于socket的物联网服务器_java 物联网通讯服务器_04

4 下载

提供的代码估计和上文的不同,下面链接是上学的时候为学长代做的毕设的全套代码,是一个实际应用,可以点击视频连接看到演示和讲解。
嵌入式软件|windows客户端|服务器源码
GITHUB 上了班之后估计很难会用到GITHUB咯

5 讲解视频

BILIBILI