Android Socket UDP 包含发送端和接收端( 两种切换方式,点对点,或者广播通讯)
不想看博客的,请直接移步下载Demo
不想看博客的,请直接移步下载Demo
不想看博客的,请直接移步下载Demo
Android中接受和发送都是需要在子线程中开启的,然后在回主线程更新UI效果,所以这里使用的是ThreadManager管理工具类管理 或者自己开启线程都一样,记得在主线程更新UI就好,
package com.example.mydemo;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.mydemo.bean.BroadCastDataBean;
import com.example.mydemo.bean.SocketDataBean;
import com.example.mydemo.utils.CalculateUtils;
import com.example.mydemo.utils.DeviceIdUtil;
import com.example.mydemo.utils.LogUtils;
import com.example.mydemo.utils.MD5ChangeUtil;
import com.example.mydemo.utils.ThreadManager;
import com.google.gson.Gson;
import com.lzh.easythread.AsyncCallback;
import com.lzh.easythread.EasyThread;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.Callable;
/**
* 服务端界面
* 这里使用EasyThread线程池管理 效率大大滴
* 有接收线程--接收数据---固定核心线程(FixedThreadPool )
* 有发送线程--回写数据---缓存线程(CachedThreadPool )
*/
public class ServerActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static String CurrentIP;
private static int BROADCAST_PORT = 7006;
private static int SEND_PORT = 7005;
private static int RECEIVE_PORT = 7003;
// private static String SEND_IP = "192.168.64.13";
private static String SEND_IP = "255.255.255.255";
// private static String BROADCAST_IP = "192.168.64.13";
private InetAddress inetAddress = null;
private DatagramSocket mSendSocket = null;
private DatagramSocket mReceiveSocket = null;
private volatile boolean isRuning = true;
private EditText mSendContent;
private Button mSend;
private Button mClear;
private TextView mReceive;
private TextView mMyIp;
private String sendStringData;
private Runnable mSendRunnable;
private EasyThread easyCacheThread;
private Runnable mReceiveRunnable;
private EasyThread easyFixed2Thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main02);
easyCacheThread = ThreadManager.getCache();
easyFixed2Thread = ThreadManager.getIO();
initView();
try {
inetAddress = InetAddress.getByName(SEND_IP);
} catch (Exception e) {
e.printStackTrace();
}
initTask();
}
private void initTask() {
//接收端-异步回调任务
startAsyncReceive();
//普通的Runnable任务,更新UI需要在主线程
//发送端:方式二点对点
//easyFixed2Thread.execute(getReceiveRunnable());
//easyCacheThread.execute(getSendRunnable(mSendContent.getText().toString().trim()));
//发送端:方式一:发送广播
easyCacheThread.execute(getSendBroadcastRunnable(mSendContent.getText().toString().trim()));
}
private void startAsyncReceive() {
// 异步执行任务
Callable<SocketDataBean> callable = new Callable<SocketDataBean>() {
@Override
public SocketDataBean call() throws Exception {
// do something
LogUtils.e("正在执行Runnable任务:%s" + Thread.currentThread().getName());
byte[] receiveData = new byte[1024];
DatagramPacket mReceivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
mReceiveSocket = new DatagramSocket(BROADCAST_PORT);
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
if (isRuning) {
try {
LogUtils.e("======ReceiveThread=====000==");
mReceiveSocket.receive(mReceivePacket);
LogUtils.e("======ReceiveThread=====111==");
String rec = CalculateUtils.byteArrayToHexString(mReceivePacket.getData()).trim();
int dd = rec.indexOf("DD");
String recIp = rec.substring(0, dd + 2);
LogUtils.e("======ReceiveThread=====222==" + recIp);
if (mReceivePacket != null) {
// Message revMessage = Message.obtain();
// revMessage.what = 1;
// revMessage.obj = recIp;
SocketDataBean socketDataBean = new SocketDataBean();
socketDataBean.setData("" + recIp);
Log.i(TAG, "handleMessage: ReceiveThread receive ip" + recIp);
return socketDataBean;
// for (int i = 0; i < 500000; i++) {
// int finalI = i;
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// mReceive.setText(recIp + "===" + finalI);
// }
// });
// }
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
// 异步回调
AsyncCallback<SocketDataBean> async = new AsyncCallback<SocketDataBean>() {
@Override
public void onSuccess(SocketDataBean user) {
// notify success;
LogUtils.e("======ReceiveThread=====onSuccess==" + user.getData());
for (int i = 0; i < 500; i++) {
mReceive.setText(user.getData() + "===" + i);
}
}
@Override
public void onFailed(Throwable t) {
// notify failed.
LogUtils.e("======ReceiveThread=====onFailed==");
}
};
// 启动异步任务
easyFixed2Thread.async(callable, async);
}
private Runnable getReceiveRunnable() {
mReceiveRunnable = new Runnable() {
@Override
public void run() {
LogUtils.e("正在执行Runnable任务:%s" + Thread.currentThread().getName());
byte[] receiveData = new byte[1024];
DatagramPacket mReceivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
mReceiveSocket = new DatagramSocket(RECEIVE_PORT);
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
if (isRuning) {
try {
LogUtils.e("======ReceiveThread=====000==");
mReceiveSocket.receive(mReceivePacket);
LogUtils.e("======ReceiveThread=====111==");
String rec = CalculateUtils.byteArrayToHexString(mReceivePacket.getData()).trim();
int dd = rec.indexOf("DD");
String recIp = rec.substring(0, dd + 2);
LogUtils.e("======ReceiveThread=====222==" + recIp);
if (mReceivePacket != null) {
// Message revMessage = Message.obtain();
// revMessage.what = 1;
// revMessage.obj = recIp;
for (int i = 0; i < 500000; i++) {
int finalI = i;
runOnUiThread(new Runnable() {
@Override
public void run() {
mReceive.setText(recIp + "===" + finalI);
}
});
}
Log.i(TAG, "handleMessage: ReceiveThread receive ip" + recIp);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
return mReceiveRunnable;
}
//
private Runnable getSendBroadcastRunnable(String data) {
mSendRunnable = new Runnable() {
@Override
public void run() {
try {
byte[] sendData = getSendData(data);
// byte[] sendData = data.getBytes();
DatagramPacket mSendPacket = new DatagramPacket(sendData, sendData.length, inetAddress, BROADCAST_PORT);
for (int i = 0; i < 2; i++) {
mSendSocket = new DatagramSocket();
mSendSocket.send(mSendPacket);
mSendSocket.setBroadcast(true);
mSendSocket.close();
}
} catch (Exception e) {
}
}
};
return mSendRunnable;
}
// private Runnable getSendRunnable(String data) {
//
// mSendRunnable = new Runnable() {
// @Override
// public void run() {
// try {
// byte[] sendData = getSendData(data);
// DatagramPacket mSendPacket = new DatagramPacket(sendData, sendData.length, inetAddress, SEND_PORT);
// for (int i = 0; i < 2; i++) {
// mSendSocket = new DatagramSocket();
// mSendSocket.send(mSendPacket);
// mSendSocket.close();
// }
// } catch (Exception e) {
//
// }
// }
// };
// return mSendRunnable;
// }
private void initView() {
mSendContent = findViewById(R.id.et_sendContent);
mSend = findViewById(R.id.btn_sendInfo);
mClear = findViewById(R.id.btnClear);
mReceive = findViewById(R.id.tv_receive);
mMyIp = findViewById(R.id.ip_info);
//Wifi状态判断
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager.isWifiEnabled()) {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
CurrentIP = getIpString(wifiInfo.getIpAddress());
mMyIp.append(CurrentIP);
LogUtils.e("mMyIp====:" + CurrentIP);
}
mSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
easyCacheThread.execute(getSendBroadcastRunnable(mSendContent.getText().toString().trim()));
}
});
mClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mReceive.setText("");
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
isRuning = false;
mReceiveSocket.close();
LogUtils.e("UDP Server程序退出,关掉mReceiveSocket,接收消息");
finish();
}
/**
* 将获取到的int型ip转成string类型
*/
private String getIpString(int i) {
return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "."
+ ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
}
private byte[] getSendData(String trim) {
LogUtils.e("TAG==输入光源数值=trim===" + trim);
String letterAndNumber = "1234abcdABCD56789";
// CharMatcher.javaDigit().matches('1');
//非空等等校验
if ("".equals(trim)) {
trim = "50";
}
int iData = Integer.parseInt(trim);
if (iData <= 0) {
iData = 0;
} else if (iData >= 63) {
iData = 63;
}
String inputSumLightData = CalculateUtils.numToHex8(iData);
// aa c5 00 -00 08 00 00 01 21-- 15 --97 dd
String str = "aac5000008000001211597dd"; //该亮度 21
/**
* 计算异或校验值
* 先截取需要做校验的字符串,再计算校验值
*/
//AA+截取数据命令+输入光源16进制 之后再做异或校验值
LogUtils.e("TAG==输入光源数值==16进制==" + inputSumLightData); //15
LogUtils.e("TAG==输入光源数值==截取==" + str.substring(6, str.length() - 6));//000800000121
String checkData = "AA" + str.substring(6, str.length() - 6);
LogUtils.e("TAG==截取的长度=" + checkData); //AA000800000121
LogUtils.e("TAG==需要计算异或的数据=" + checkData + inputSumLightData); //AA00080000012115
String hexXORData = CalculateUtils.get16HexXORData(checkData + inputSumLightData);
LogUtils.e("TAG==发送的异或结果=" + hexXORData);
//AA+截取数据命令+输入光源16进制 之后再做异或校验值+DD结尾
sendStringData = str.substring(0, str.length() - 6) + inputSumLightData + hexXORData + "dd";
LogUtils.e("TAG==发送的结果=" + sendStringData);
//16进制String转换成byte字节数组
byte[] bytes = CalculateUtils.hexString2Bytes(sendStringData);
return bytes;
}
}
下面是上面使用到的工具类:略~~可以下载具体Demo 里面全部有,还有PC端调试工具
|