APP与终端设备通信经验三(具体情形介绍)

一、过程还原:
1.1.P2P模型
P2P(Peer to Peer)点对点通信模型,终端与手机是对等网络,由于终端IP和端口固定,最初由手机建立信令报文传输链路(常链路),之后码流报文传输链路(短链路)由终端根据手机端的相关的信令报文建立。
1.2.手机连接终端WIFI
终端释放一个固定名称热点(如,Wisdom_Wifi),IP为固定192.168.10.16,服务端口固定为9999
手机端打开WIFI,手动连接(Wisdom_Wifi)
手机WIFI连接成功,终端为其分配IP地址192.168.10.xx
1.3.信令链路建立
手机端主动 connect 192.168.10.16:9999,建立信令传输链路TCP0,用于手机和终端之间信令的接收和发送
手机端周期性(如,10秒)发送设备状态查询指令到终端,终端应答之(相当于长连接,维持通信链路)

备注: 到此,手机与终端已经正常连接,手机端能正常获取终端设备的各项状态,如 果不需要传输视频和文件,就一直这么运行。如果手机端需要请求视频和文件 传输,则进入1.3流程。
1.4.码流链路建立
说明:以请求实时视频流程来描述
用户在手机端操作请求第1通道实时视频
手机通过TCP0链路发送请求实时视频指令0x9101,该指令包含手机端处理视频流的IP、PORT
终端在TCP0链路上收到手机端实时视频传输请求,提取出消息中的IP、PORT,建立码流传输链路TCP1
TCP1码流传输链路建立成功,终端在链路TCP1上按RTP协议传输视频码流到手机
手机端接收解析TCP1链路上的码流协议包,提取出视频流,渲染出视频画面。

二、

第一步建立 一个连接socket,连接终端设备的iP和端口号

      //实例化一个Socket对象
            socket = new Socket();

            //与对应的ip、端口进行连接,先要把桥建好
            socket.connect(new InetSocketAddress(ip, port), 3000);
            Log.i("socketThread","@@@connected");
            if (socket.isConnected()) {
                client = new SocketThreadTM.Client(socket,mMessageListener);
                //打开对应的输入/输出流监听
                client.start();
                isStart=true;
                connectedState.IsConnected(true);
            }else{
                isStart=false;
                connectedState.IsConnected(false);
            }
        } catch (IOException e) {
            Log.v("socketThread", "@@@E");
            e.printStackTrace();
            isStart=false;
            connectedState.IsConnected(false);
        }

定义的接口用于监听socket连接成功与否

public interface ConnectedState {
	public void IsConnected(boolean conn);
}

当连接成功后,会打开输入输出流的线程

  public class Client {

        private ClientInputThreadTM in;
        private ClientOutputThread out;

        public Client(Socket socket, MessageListener mMessageListener) {
            //用这个监听输入流线程来接收信息
            in = new ClientInputThreadTM(socket);
            in.setMessageListener(mMessageListener);
            //以后就用这个监听输出流的线程来发送信息了
            out = new ClientOutputThread(socket);
        }

        public void start() {
            in.setStart(true);
            out.setStart(true);
            in.start();
            out.start();
        }

        // 得到读消息线程
        public ClientInputThreadTM getIn() {
            return in;
        }

        // 得到写消息线程
        public ClientOutputThread getOut() {
            return out;
        }
    }

里面的构造方法里注册数据监听的方法
在这里启动了输入输出线程

看看输入输出线程对应实现细节
输入线程用于监听终端发给app的数据

 public ClientInputThreadTM(Socket socket) {
        this.socket = socket;
        try {
            ois = socket.getInputStream();
            dis = new DataInputStream(new BufferedInputStream(ois));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

拿到socket的输入流ois,同时包装下DataInputStream

同时线程的run方法,
int result = dis.read(b);
msg=“9102”;
messageListener.Message(msg);
msg = “”;
写出for循环表明一直监听终端数据

当退出for循环监听也随之结束。

输出线程用于app主动给终端发数据

public ClientOutputThread(Socket socket) {
		this.socket = socket;
		try {
			dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
		} catch (IOException e) {
			e.printStackTrace();

		}
	}


	// 这里处理跟服务器是一样的
	public void sendMsg(byte[] msg) {
		this.msg = msg;
		synchronized (this) {
			notifyAll();
		}
	}

	@Override
	public void run() {
		try {
			while (isStart) {
				if (msg != null) {
					Log.i(Tag,"sendmsg:"+ StringUtils.bytesToHexString(msg));
					dos.write(msg);
					dos.flush();
					msg=null;
					synchronized (this) {
						wait();// 发送完消息后,线程进入等待状态
					}
				}
			}
			dos.close();// 循环结束后,关闭输出流和socket
			if (socket != null)
				socket.close();
		} catch (InterruptedException e) {
			e.printStackTrace();
			messageListener.Message("outOline");
		} catch (IOException e) {
			e.printStackTrace();
			messageListener.Message("outOline");
//		}catch (ErrnoException e){
//			e.printStackTrace();
//			messageListener.Message("outOline");
//
		}catch (Exception e){
			e.printStackTrace();
			messageListener.Message("outOline");
		}
	}

这里使用了Thread 的notify和wait的方式,所错了是object的。居然是所有类的方法,查阅资料
发现:

1、wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写;
2、notify方法用于唤醒线程。我们看到输出线程的发送方法就只调用了notifyall方法。应该是唤醒这个线程。
3、notify方法只是唤醒线程。还没有释放锁。当遇到wait方法才会释放锁。

总结:本片介绍了手机和终端通过socket流建立通信的过程。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值