项目简介:
该项目把手机上的导航信息发送到汽车仪表上,并在仪表上显示,实现手机地图到仪表的投射。发送端程序用Java编写,接收端程序用C++,Qt编写。仪表和手机之间通过wifi通信。服务器:仪表,客户端:手机。
工作原理:
当仪表开机后,定时的对外广播本机的IP及端口号。手机导航程序获取广播并解析仪表的地址信息,然后向仪表发送TCP连接请求。当连接建立后,即可实现通信。手机程序截取图片,然后发送到仪表,仪表接收到图片后,把图片在屏幕上显示出来。
遇到的问题:
当手机和仪表建立socket 连接之后,手机导航程序由“导航”模式切换到“投屏”模式,当socket连接断开之后,手机导航程序由“投屏”模式切换到“导航”模式。
ps:导航模式,在手机上显示地图信息及提示信息。投屏模式,手机上只显示提示信息,不显示地图信息。
那么问题来了,手机如何主动的获取socket连接的状态呢?而且只要连接的状态发生变化,手机就会及时的获知这一信号。
实现方法:
关键字:监视器 发送立即数
建立两个socket通道
private Socket socketCtrl = null;//由仪表向手机导航程序发送设置信号,比如设置屏幕的分辨率。
private Socket socketPic = null;//由手机向仪表发送导航信息。
1.定义一个监视器,当socket连接的状态发生改变时,调用该接口函数。代码只摘取了关键的部分,下同。
interface ProCtrlInfoListener {
void onConnectChanged(boolean connectState);//该接口由调用它的程序来具体的实现
}
2.当连接建立时,调用该接口。
if (socketCtrl.isConnected() && socketPic.isConnected() ) {
if(proCtrlInfoListener != null) {
proCtrlInfoListener.onConnectChanged(true);//调用方程序进行相应的处理
}
}
3.当连接断开时,调用该接口。
思路:发送立即数。接收端接收到该数据时,默认的处理方式为丢弃。如果连接已断开,则抛出异常,在处理异常时调用监视器。
/*建立一个线程,用来接收控制信号*/
private class ThreadCtrl extends Thread {
private Socket socket;
private boolean flagState;
//略
public void run() {
while(flagState && flag) { //实时等待控制信号的发来
try {
is.read(dataCtrl);//当没有控制信息发来时,程序阻塞在is.read(dataCtrl)处。当有控制信息发来或者socket连接断开时,is.read(dataCtrl)返回
} catch (IOException e1) {
e1.printStackTrace();
}
//略
/*当is.read(dataCtrl)返回,执行socket.sendUrgentData(0xFF)。如果socket连接断开,则执行p.onConnectChanged(false);
flagState = false;中断while()循环。*/
try {
socket.sendUrgentData(0xFF);
} catch (IOException e) {
System.out.println("~~~~~连接已断开~~~~~");
proCtrlInfoListener.onConnectChanged(false);//调用方程序进行相关的处理
flagState = false;
}
}
}
}
以上代码是不完整的,只抠出来了关键的部分。
经测试,当服务器关闭时,客户端能够及时的获取这一信号。
欢迎讨论,指正!