android udp定时发送,Android Socket基于UDP协议通信
首先我們要知道UDP通信協議是Socket通信的一種實現方式,Socket通信一般有兩種通信方式:基于TCP協議、基于UDP協議。這兩者的差別和優缺點就不說了,這里主要講一下基于UDP協議的實現。
基本原理
基于UDP的通信都是通過java.net.DatagramSocket這個類來實現的,我們常用的有connect()、disConnect()、send()、receive()幾個方法。通過方法名我們可以輕易區分出用法。另一個需要知道的就是DatagramPacket類,如果把DatagramSocket比作管道的話,DatagramPacket就是管道中運輸的物品,也就是說,它就是數據的載體。
DatagramSocket:
public DatagramSocket()throws SocketException {
this(0);
}
public DatagramSocket(int aPort)throws SocketException {
checkPort(aPort);
createSocket(aPort, Inet4Address.ANY);
}
public DatagramSocket(int aPort, InetAddress addr)throws SocketException {
checkPort(aPort);
createSocket(aPort, (addr == null) ? Inet4Address.ANY : addr);
}
三個構造方法,我們可以指定端口和IP,也可以不指定,在發送數據的時候,在數據包中指定。
DatagramPacket:
public DatagramPacket(byte[]data, int length) {…}
public DatagramPacket(byte[]data, int offset, int length) {…}
public DatagramPacket(byte[]data, int offset, int length, InetAddress host, int aPort) {…}
public DatagramPacket(byte[]data, int length, InetAddress host, int port) {…}
so 我們可以看到可以在數據包中設置ip和端口,所以如果連接時不指定也是可以的。
基本操作
1、connect new出一個DatagramSocket對象,設置端口和IP,connect();
2、send 創建一個DatagramPacket對象,socket.send(packet)發送數據;
3、receive 創建一個DatagramPacket對象,socket.receive(package)接收數據;
創建一個連接
使用connect方法創建一個Socket連接
public void connect() {
if (mSocket == null || mSocket.isClosed()) {
try {
//獲取連接 ip:192.168.1.3 port:11069
InetAddress address = InetAddress.getByName(Command.udp_address);
mSocket = new DatagramSocket();
mSocket.connect(address, Command.udp_port);
messageQueue = new ArrayList < String > ();
//開啟接收線程
mReceiveThread = new ReceiveThread();
mReceiveThread.start();
} catch (SocketException e) {
e.printStackTrace();
}
}
}
定時發送數據保持通信
要保持通信的話,肯定要用到線程了,定時發送數據的話,可以用Handler,或者也可以使用AlarmManager。這里使用Handler實現就好了。
寫的時候看了一堆博客,發送的時候都是new 出一個Thread進行發送數據,發送之后寫接收數據的代碼,而且沒有進行回收或者怎樣,只能最后通過GC回收,當然大體上看是沒毛病的,但是其實有很大的問題!因為我項目要求收到服務器的應答之后做一些相應的操作,,然后,然后,,因為每一個線程都在等待著接收數據,所以服務端回復一條數據之后,這邊每個線程都作出了回應(回復服務器一條不一樣的數據),10s創建一個線程發送數據,服務器過了一段時間再回復,然后就瞬間爆炸!
所以,,接收和發送應該是要分開的,不能阻塞在同一個線程中。一開始想到Handler的原理和機制,想模仿它死循環從一個隊列中取數據,如果有數據就發送,想法是沒毛病,也能發送,但是當我想在發送成功之后從列表中remove掉這條數據之后就不行了,線程阻塞了。具體原因應該是造成死鎖了,因為數據列表是定義在主線程,然后一直在被工作線程占用著,獲取不到對象進行remove操作,等待一定時間后,直接crash掉了(我的分析是這樣的)。
ok,那就寫兩個線程好了,一個SendThread,一個ReceiveThread,另外通過Handler控制10s定時發送。
發送線程:
public class SendThread extends Thread {
@ Override
public void run() {
super.run();
try {
if (mSocket == null || mSocket.isClosed())
return;
if (messageQueue.size() < 1)
return;
//發送
final String data = messageQueue.get(0);
byte[]datas = data.getBytes();
InetAddress address = InetAddress.getByName(Command.udp_address);
final DatagramPacket packet = new DatagramPacket(datas, datas.length, address, Command.udp_port);
mSocket.send(packet);
Logs.e("ConnectManager", "send success data is:" + data);
messageQueue.remove(0);
} catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
接收線程:
private class ReceiveThread extends Thread {
@ Override
public void run() {
super.run();
if (mSocket == null || mSocket.isClosed())
return;
try {
byte datas[] = new byte[512];
DatagramPacket packet = new DatagramPacket(datas, datas.length, address, Command.udp_port);
mSocket.receive(packet);
String receiveMsg = new String(packet.getData()).trim();
Logs.e("ConnectManager", "receive msg data is:" + receiveMsg);
mHandler.sendEmptyMessage(2);
} catch (IOException e) {
e.printStackTrace();
}
}
}
我們可以看到ReceiveThread中只接收了一次數據,那如何實現一直保持通信?接收消息?Handler!接收到消息之后我們通過Handler發送了一條消息,這條消息干嘛的呢,重啟這個線程,也就是讓它繼續接收數據。 這樣的話,就保證了只有一個線程在接收數據。
private Handler mHandler = new Handler() {
@ Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 2) {
mReceiveThread.interrupt();
mReceiveThread = null;
mReceiveThread = new ReceiveThread();
mReceiveThread.start();
}
}
};
同樣,定時發送數據也是通過Handler實現的,每10s發送一個消息,讓socket發送一個數據包,并且給自己發送一個10s后發送的同樣的消息,反正就是自己控幾自己啦。
發送消息:
public void sendPackageRegister() {
String content = "(1001," + Command.deviceId + ",register)";
messageQueue.add(content);
mSendThread.interrupt();
mSendThread = null;
mSendThread = new SendThread();
mSendThread.start();
}
最后,記得停掉Handler一直發送數據,停掉線程。
總結
以上是生活随笔為你收集整理的android udp定时发送,Android Socket基于UDP协议通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言入口及出口参数说明,麻烦帮忙指出一
- 下一篇: android与gradle版本,and