STM32F4+WIFI模块TCP链接服务器,服务器与安卓客户端Websocket长链接;实现监控信息实时推送。

  哈哈哈哈哈!这是笔者第一次写这种东西,项目是我们大二的一个大创组的项目:

1>硬件端:stm32f429,红外线感应,esp8266模块,ov5640摄像头,步进电机,等等。

   主要是采集移动物体的图像jpg,通过无线传输模块传递给服务器。这里将硬件当作tcp客户端。

2>服务器端:java写的,Java建立tcp服务器代码如下:

public static void main(String[] args) throws IOException{
        ServerSocket ss=new ServerSocket(5670);//tcp服务器
        socketserve socketServer = new socketserve(2017);//websocket服务器
        socketServer.start();
        while(true) {
        Socket s=ss.accept();
        socketT t=new socketT(s,i,socketServer );
        new Thread(t).start();
        i++;
        }
  }
}
///  硬件的tcp服务器
class socketT implements Runnable{
      private Socket client;
      private int i;//照片个数
  private socketserve android;
      InputStream in=null;
      public socketT(Socket client,int i,socketserve android ) {
        this.client=client;
        this.i=i;
        this.android=android;
       }
    @Override
    public void run() {
        int j,c=0;
        int d=0;
        try {
            in=client.getInputStream();
            byte []data =new byte[300000];
            byte []data1 = null;
            for(j=0;d!=0xFF||c!=0xD9;) {
               d=c;
               c=in.read();
               if(c!=-1) {
               data[j]=(byte)c;
               j++;
               }
            }
               data[j]=-2;
               data1=new byte[j+1];
               for(;j>=0;j--)
                   data1[j]=data[j];        
            //发送给app
           android.sendToclient(data1);//websocket 服务器主动推送给手机
            //存入电脑
            FileOutputStream op=new FileOutputStream(new File("D:/p/"+Integer.toString(i)+".jpg"));
              op.write(data1);
              op.close();
              ///人脸识别调用
         /*    new Thread(new Runnable() {
                  byte[] data2=null;
                     @Override
                     public void run() {
                         picture.FeatureOrbLannbased("D:/p/"+Integer.toString(i)+".jpg","D:/p3/"+Integer.toString(i)+".jpg");
                         FileInputStream oo;
                         try {
                             oo = new FileInputStream(new File("D:/p3/"+Integer.toString(i)+".jpg"));
                             data2=new byte[oo.available()];
                                oo.read(data2);
                                android.sendToclient(data2);
                         } catch (Exception e) {
                             e.printStackTrace();
                         }
                         }
                 }).start();*/
            
        } catch (IOException e) {
            
            e.printStackTrace();
        }finally {
            try {
                in.close();
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            
        }
        
        
    }

这里,我们不知道一张照片的大小是多大,所以只能用其结束符进行捕捉:jpg图片的文件是十六进制数,每张jpg图片以0xFF 0xD8开始,以0xFF 0xD9结束;所以我们从client 得到的inputsteam中读取字节,读到结束符的时候就代表一张图片的数据已经全部接收,就可以转化为想要的图片了。 值得我们注意的是:有时候inputsteam中的字节已经全部读取完毕,但是还没读到结束符;原因是一般是这样的:客户端(无论是硬件,还是在电脑上模拟的)发送大文件时候是一段一段发送的,比如我的硬件是每次发送1024个字节,那一张高质量图片要将近1M,所以不能一次发送,于是就必须等待指导有结束符才结束。

还有:这里是tcp短链接,要想长连接只需将其中的读取字节部分写入死循环即可,就是处理完一张照片,将byte[] data数组重新初始化,继续从in中读取。in和client一旦关闭,tcp断开。当然长连接已不是一直的,据说是2个小时会断开,我们用的局域网,额额额,晚上建立链接,早上起来还没断。

3>服务器端的websocket长连接;这是好东西,可以实现服务器端的信息向客户端的推送,实现起来也很简单。狠狠的踢开http(hahahahaha!);httpok也有封装这类东西。

public class socketserve extends WebSocketServer{
    public socketserve(int port)throws UnknownHostException{
        super(new InetSocketAddress(port));
    }
    public socketserve(InetSocketAddress address) {
        super(address);
    }

    @Override
    public void onClose(WebSocket webSocket, int i, String s, boolean b) {
        System.out.println("duankai");
    }

    @Override
    public void onError(WebSocket webSocket, Exception e) {
         if (null != webSocket) {
                webSocket.close(0);
            }
            e.printStackTrace();
        
    }

    @Override
    public void onMessage(WebSocket webSocket, String s) {
    }

    @Override
    public void onOpen(WebSocket webSocket, ClientHandshake clienthandshake) {
          sendToclient("OPEN");
          System.out.println("有客户已经链接上服务器");
          }

    @Override
    public void onStart() {
        // TODO Auto-generated method stub
        
    }
    //
    public void sendToclient (String message) {
        Collection<WebSocket> connections = connections();
        //将消息发送给每一个客户端
        for (WebSocket client : connections) {//这里需要判断客户端是否是硬件的主人,如果是就发送信息
            client.send(message);
        }
        
    }
     public void sendToclient(ByteBuffer b) {
            Collection<WebSocket> connections = connections();
            //将消息发送给每一个客户端
            for (WebSocket client : connections) {
                client.send(b);
            }
        }
     public void sendToclient(byte[] message) {
            Collection<WebSocket> connections = connections();
            //将消息发送给每一个客户端
            for (WebSocket client : connections) {
                client.send(message);
            }
        }
    
    
}

很简单,可能是我们使用的太低级,嗯!可以发送String   byte[]   bytebuffer三种;主动推送给客户端。

4>android客户端;我主要说我们的通信链接模块

我们将其写道一个后台运行中,当出发app的某个开关之后,后台一直运行,直到将他杀死。

public class service extends Service {
    private websocket client;
    private static final String url = "ws://你的服务器ip:你的服务器端口/";
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
      @Override  
        public void onCreate() {  
        
        }  
      
        @Override  
        public void onDestroy() {
            client.close();
           
        }  
      
        @Override  
        public void onStart(Intent intent, int startid) {
            websocket_init();
    
        }  
                
/

    private void websocket_init(){
             client = new websocket(URI.create(url)) {
                @Override
                public void onMessage(ByteBuffer message) {
                    byte[] dat=new byte[message.remaining()];
                    message.get(dat, 0, dat.length);//得到服务器端推送信息
                    FileOutputStream fout;
                    try {
                        fout = new FileOutputStream(new File(Environment.getExternalStorageDirectory()+"/dachuang/",Integer.toString(data.shu()+1)+".jpg"));//存入手机固定的内存文件夹
                        fout.write(dat);
                        fout.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    addnotification("接收到警报消息,点击查看");//添加消息栏提醒
                }

                @Override
                public void onMessage(String message) {
                    if(message=="OPEN");//接收到服务器的消息,这个消息是   ,自己看吧,对照服务器端代码
                    addnotification("链接成功");
                }
                
            };
            client.connect();
    }
    
    /    ///
private  void addnotification(String str) {
            NotificationManager manager=(NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
                    Notification notification=new Notification();
                    //设置显示在手机最上边的状态栏的图标
                    notification.icon=R.drawable.family;
                    notification.tickerText="注意了,我被扔到状态栏了";
                    notification.defaults=Notification.DEFAULT_SOUND;
                    notification.defaults =Notification.DEFAULT_VIBRATE;
                    notification.audioStreamType=android.media.AudioManager.ADJUST_LOWER;
                    Intent intent=new Intent(this,option_3.class);
                    PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_ONE_SHOT);
                    //点击状态栏的图标出现的提示信息设置
                     notification.setLatestEventInfo(this,"警报信息:",str,pendingIntent);
                    manager.notify(1,notification);
            }

}

N>是的,也许你会问,你需要jar,那就去下载吧!https://download.csdn.net/download/lixinkailixinkai/10623020

还有人脸识别:下回再说。

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值