Udp socket通信和Tcp socket通信原理,请参考:
《Android中关于Socket通信数据大小,内存缓冲区和数据可靠性的一点调查》
核心代码
初始化UDP socket和接收Packet:
mUdpSocket = new DatagramSocket(UDP_SOCKET_PORT);
mRecvPacket = new DatagramPacket(mReceiveByte, PACKAGE_BUFFER_SIZE);
数据发送和分包:
synchronized(mLock) {
InetAddress targetAddress = InetAddress.getByName(UDP_SOCKET_HOST);
for( int i = 0; i < packageNum; i++ ){
if(i == packageNum - 1 ){
mSendBuffer.dataBuf = new byte[(size + 8) - i * PACKAGE_BUFFER_SIZE];
System.arraycopy(buffer, i * PACKAGE_BUFFER_SIZE, mSendBuffer.dataBuf, 0, (size + 8) - i * PACKAGE_BUFFER_SIZE);
}else{
mSendBuffer.dataBuf = new byte[PACKAGE_BUFFER_SIZE];
System.arraycopy(buffer, i * PACKAGE_BUFFER_SIZE, mSendBuffer.dataBuf, 0, PACKAGE_BUFFER_SIZE);
}
Log.i(TAG,"sendDataToDashboard,write.size()=" + mSendBuffer.dataBuf.length);
DatagramPacket packet = new DatagramPacket(mSendBuffer.dataBuf, mSendBuffer.dataBuf.length, targetAddress, UDP_SOCKET_PORT);
mUdpSocket.send(packet);
}
}
数据接收和解析:
readData()
完整代码实现:
public class AndroidUdpSocketService extends Service {
private static final String TAG = AndroidUdpSocketService.class.getName();
private static DatagramSocket mUdpSocket;
private static DatagramPacket mRecvPacket;
private static BackgroundExecutor mBackgroundExecutor;
private byte[] mReceiveByte = new byte[PACKAGE_BUFFER_SIZE];
private boolean isAndroidUdpSocketLive = false;
private static final String UDP_SOCKET_HOST= "255.255.255.255";
private static final int UDP_SOCKET_PORT= 6002;
private static final int READ_BUFFER_LENGTH = 1024;
private static final Object mLock = new Object();
private static final int PACKAGE_BUFFER_SIZE = 50000;
class SocketDataBuffer
{
byte[] dataBuf;
int flag; // 0,middle data; 1,the last data
};
static SocketDataBuffer mSendBuffer;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"onCreate");
mBackgroundExecutor = BackgroundExecutor.get();
mSendBuffer = new SocketDataBuffer();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG,"onStartCommand");
createNotificationChannel();
new InitUdpSocketThread().start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG,"onDestroy");
releaseLastSocket();
}
@Override
public void onLowMemory() {
super.onLowMemory();
Log.i(TAG,"onLowMemory");
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
Log.i(TAG,"onTrimMemory");
}
private void createNotificationChannel() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String id = "car_launcher_02";
CharSequence name = "AndroidUdpSocketService";
String description = "Udp Socket Service";
NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_MIN);
mChannel.setDescription(description);
mChannel.setSound(null, null);
mNotificationManager.createNotificationChannel(mChannel);
Notification notification = new Notification.Builder(this)
.setChannelId(id)
.setSmallIcon(R.drawable.ic_home)
.build();
startForeground(12,notification);
}
class InitUdpSocketThread extends Thread {
@Override
public void run() {
super.run();
try {
Log.i(TAG,"InitSocketThread,new socket");
//Start Heartbeat
//mHandler.postDelayed(mHeartbeatRunnable, HEART_BEAT_RATE);
//Create tcp socket connect
mUdpSocket = new DatagramSocket(UDP_SOCKET_PORT);
mRecvPacket = new DatagramPacket(mReceiveByte, PACKAGE_BUFFER_SIZE);
mUdpSocket.setSendBufferSize(1024*1024*10);
mUdpSocket.setReceiveBufferSize(1024*1024*10);
Log.i(TAG,"new Socket,mUdpSocket.getSendBufferSize()=" + mUdpSocket.getSendBufferSize());
Log.i(TAG,"new Socket,mUdpSocket.getReceiveBufferSize()=" + mUdpSocket.getReceiveBufferSize());
isAndroidUdpSocketLive = true;
readDataFromDashboard();
} catch (IOException e) {
//e.printStackTrace();
Log.i(TAG,"new Socket,IOException" + e.getMessage());
}
}
}
private void releaseLastSocket() {
isAndroidUdpSocketLive = false;
Log.i(TAG,"releaseLastSocket2");
if (null != mUdpSocket) {
Log.i(TAG,"releaseLastSocket2,mSocket.isClosed()=" + mUdpSocket.isClosed());
mUdpSocket.close();
mUdpSocket = null;
}
}
public static boolean sendData(final int frameType,final int frameID,final byte[] data) {
// Log.i(TAG,"sendData,mUdpSocket != null," + (mUdpSocket != null));
// Log.i(TAG,"sendData,mUdpSocket.isClosed()," + (mUdpSocket.isClosed()));
// Log.i(TAG,"sendData,mUdpSocket.isConnected()," + (mUdpSocket.isConnected()));
if( mUdpSocket != null && !mUdpSocket.isClosed()) {
mBackgroundExecutor.submit(new Runnable() {
@Override
public void run() {
//do something
Log.i(TAG, "sendData,start");
int size = data.length;
byte buffer[] = new byte[8 + size];
buffer[0] = (byte) 0xA6;
buffer[1] = 0x6A;
buffer[2] = (byte) frameType;
buffer[3] = (byte) ((size & 0xff000000) >> 24);
buffer[4] = (byte) ((size & 0x00ff0000) >> 16);
buffer[5] = (byte) ((size & 0x0000ff00) >> 8);
buffer[6] = (byte) ((size & 0x000000ff));
buffer[7] = (byte) frameID;
System.arraycopy(data, 0, buffer, 8, size);
Log.i(TAG, "sunxiaolin,sendData,size=" + size);
//Log.i(TAG, "sendData,data=" + data);
//Log.i(TAG, "sendData,buffer=" + Utils.printHexBinary(buffer));
int packageNum = (size + 8) / PACKAGE_BUFFER_SIZE + 1 ;
Log.i(TAG, "sendDataTo,packageNum=" + packageNum);
try {
synchronized(mLock) {
InetAddress targetAddress = InetAddress.getByName(UDP_SOCKET_HOST);
for( int i = 0; i < packageNum; i++ ){
if(i == packageNum - 1 ){
mSendBuffer.dataBuf = new byte[(size + 8) - i * PACKAGE_BUFFER_SIZE];
System.arraycopy(buffer, i * PACKAGE_BUFFER_SIZE, mSendBuffer.dataBuf, 0, (size + 8) - i * PACKAGE_BUFFER_SIZE);
}else{
mSendBuffer.dataBuf = new byte[PACKAGE_BUFFER_SIZE];
System.arraycopy(buffer, i * PACKAGE_BUFFER_SIZE, mSendBuffer.dataBuf, 0, PACKAGE_BUFFER_SIZE);
}
Log.i(TAG,"sendData,write.size()=" + mSendBuffer.dataBuf.length);
DatagramPacket packet = new DatagramPacket(mSendBuffer.dataBuf, mSendBuffer.dataBuf.length, targetAddress, UDP_SOCKET_PORT);
mUdpSocket.send(packet);
}
}
Log.i(TAG, "sunxiaolin,sendData,write success.");
} catch (IOException e) {
//e.printStackTrace();
Log.i(TAG, "sunxiaolin,sendData,write failed," + e.getMessage());
}
}
});
}
else{
Log.i(TAG,"mSocket is null");
}
return true;
}
int mTotalSize = 0;
int mFrameSize = 0;
byte[] mReadBuffer;
private void readData(){
new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG,"readDatastart");
while( isAndroidUdpSocketLive ){
if( mUdpSocket != null && !mUdpSocket.isClosed()) {
try {
mUdpSocket.receive(mRecvPacket);
String strReceive = new String(mRecvPacket.getData(), 0, mRecvPacket.getLength());
int readSize = mRecvPacket.getLength();
int head;
Log.i(TAG,"readDataread.size()=" + mRecvPacket.getLength());
mRecvPacket.setLength(PACKAGE_BUFFER_SIZE);
if( readSize > 8 ){
head = ((mRecvPacket.getData()[0] & 0xff) << 8) | mRecvPacket.getData()[1];
if( head == 0xA66A ){
//Start
mFrameSize = ( (mRecvPacket.getData()[3] & 0xff) << 24 | (mRecvPacket.getData()[4] & 0xff) << 16 | (mRecvPacket.getData()[5] & 0xff) << 8 | (mRecvPacket.getData()[6] & 0xff) );
if(mFrameSize >= 0){
mReadBuffer = new byte[mFrameSize + 8];
}
mTotalSize = 0;
}
if( mTotalSize < mFrameSize + 8 && (mTotalSize + readSize) <= mFrameSize + 8)
{
System.arraycopy(mRecvPacket.getData(), 0, mReadBuffer, mTotalSize, readSize);
mTotalSize += readSize;
if( mTotalSize == mFrameSize + 8){
//End
byte[] imageBuffer = new byte[mFrameSize];
System.arraycopy(mReadBuffer, 8, imageBuffer, 0, mFrameSize);
mFrameSize = 0;
Log.i(TAG,"readDatam,TotalSize=" + mTotalSize);
Log.i(TAG,"readData,imageBuffer.size=" + imageBuffer.length);
Message msg = new Message();
msg.what = AudioFragment.UPDATE_UI;
msg.obj = imageBuffer;
AudioFragment.mCarHandler.sendMessage(msg);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}