UDP是一個(gè)無連接協(xié)議葫松,傳輸數(shù)據(jù)之前源端和終端不建立連接。對(duì)于udp來說并沒有服務(wù)端和客戶端底洗,都是發(fā)送端和接收端腋么。
android中使用DatagramSocket來創(chuàng)建udp的socket,使用DatagramPocket來存儲(chǔ)數(shù)據(jù)亥揖。
1珊擂、創(chuàng)建DatagramSocket
image
2、發(fā)送數(shù)據(jù)
image
3费变、發(fā)送文件
image
4摧扇、接收數(shù)據(jù) 這里的udpSocket.receive(DatagramPacket)阻塞方法,要在子線程中進(jìn)行
image
整體的代碼
public class DealUdpService extends Service {
public DealUdpService() {
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public class MyBinder extends Binder {
private DatagramSocket udpSocket;
private ExecutorService mExecutorService;//線程池
private String netIP = "192.168.2.223";//目標(biāo)ip
private int netPort = 9000;//目標(biāo)端口
private int heartTime = 5000;//間隔時(shí)間胡控,接收和發(fā)送數(shù)據(jù)
private Handler uHandler = new Handler();
private int linkCount = 0;//連接次數(shù)
public void startUdp() {
if (mExecutorService == null) {
mExecutorService = Executors.newCachedThreadPool();
}
mExecutorService.execute(initSocket);
}
private Runnable initSocket = new Runnable() {
@Override
public void run() {
try {
// InetAddress address = InetAddress.getByName(netIP);
//這里必須要設(shè)置null扳剿,不然下面設(shè)置本地端口會(huì)報(bào)異常
udpSocket = new DatagramSocket(null);
udpSocket.setReuseAddress(true);
//設(shè)置本地端口
udpSocket.bind(new InetSocketAddress(9000));
//udpSocket.connect(address,netPort);
linkCount = 1;
uHandler.post(jieshou);
uHandler.post(fasong);
}catch (Exception e){
e.printStackTrace();
linkCount++;
Log.i("sun", "連接失敗,進(jìn)行第" + linkCount + "次重連");
uHandler.postDelayed(new Runnable() {
@Override
public void run() {
mExecutorService.execute(initSocket);
}
}, heartTime);
}
}
};
private Runnable fasong = new Runnable() {
@Override
public void run() {
sendData("123456789");
Log.i("sun", "發(fā)送數(shù)據(jù)");
}
};
//發(fā)送數(shù)據(jù)昼激,可以暴露出去,在其他地方調(diào)用
private void sendData(String ss) {
mExecutorService.execute(new Runnable() {
@Override
public void run() {
try {
//uHandler.postDelayed(fasong,5000);定時(shí)發(fā)送
byte[] data = ss.getBytes();
DatagramPacket send = new DatagramPacket(data, data.length,new InetSocketAddress(netIP, netPort));
udpSocket.send(send);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 發(fā)送文件
*/
private void sendFile(){
mExecutorService.execute(new Runnable() {
@Override
public void run() {
try {
InputStream in = getAssets().open("meet.docx");
int size = -1;
byte[] car = new byte[1024];
while ((size = in.read(car, 0, 1024)) != -1) {
//這里是發(fā)送文件锡搜,實(shí)際中應(yīng)該是在對(duì)方回應(yīng)后在發(fā)送下一包橙困,添加說明數(shù)據(jù)
DatagramPacket send2 = new DatagramPacket(car, car.length,new InetSocketAddress(netIP, netPort));
udpSocket.send(send2);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private Runnable jieshou = new Runnable() {
@Override
public void run() {
Log.i("sun", "執(zhí)行接收");
receiveData();
}
};
private void receiveData() {
mExecutorService.execute(new Runnable() {
@Override
public void run() {
try {
//uHandler.postDelayed(jieshou,5000);
byte[] result = new byte[1024];
while (true) {
DatagramPacket reveive = new DatagramPacket(result, result.length, new InetSocketAddress(netIP, netPort));
udpSocket.receive(reveive);
byte[] data = reveive.getData();
String ss = new String(data,0,reveive.getLength());
String cc = bytesToHex(data);
Log.i("sun", cc + "==接收到數(shù)據(jù)==" + ss);
}
} catch (Exception e) {
Log.i("sun","接收異常=="+e);
}
}
});
}
/**
* 將接收到byte數(shù)組轉(zhuǎn)成String字符串
*
* @param bytes 接收的byte數(shù)組 16進(jìn)制的數(shù)組
* @return string字符串
*/
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
String hex = Integer.toHexString(aByte & 0xFF);
if (hex.length() < 2) {
sb.append(0);
}
sb.append(hex);
}
return sb.toString();
}
public void destory(){
uHandler.removeCallbacksAndMessages(null);
udpSocket.disconnect();
udpSocket.close();
}
}
}