超时重发

package com.ubtechinc.base;


import java.util.ArrayList;
import java.util.List;


import android.os.SystemClock;


import com.ubtechinc.base.PublicInterface.BlueToothInteracter;


class BUFFER_DATA
{
public byte[] datas;
public int nLen;
public long lastSendTime;
public int resenTime;
}


/**
 * 设备处理的纯种
 * @author juntian
 *
 */
public class DeviceProcessThread extends Thread{

public interface DeviceProcessThreadCallBack{
void onSendData(byte[] data, int len);
}

/**
* 与设备交互的接口
*/
//private BlueToothInteracter mBlueToothInteracter;
private ProtocolPacket mPacketRead;
private DeviceProcessThreadCallBack mCallBack;

/**
* 重发队列
*/
private List<BUFFER_DATA> mListReSend;
private boolean mRun = true;

public DeviceProcessThread( DeviceProcessThreadCallBack callback ){
mCallBack = callback;
mPacketRead = new ProtocolPacket();
mListReSend = new ArrayList<BUFFER_DATA>();
}

/**
* 发送数据
* @param datas
* @param nLen
*/
public void sendData(byte[] datas, int nLen){
synchronized(this){
BUFFER_DATA data = new BUFFER_DATA();

data.datas = datas;
data.nLen = nLen;
data.lastSendTime = SystemClock.uptimeMillis();
data.resenTime = 0;

mListReSend.add(data);

if (mCallBack != null){
mCallBack.onSendData(datas, nLen);
}
}
}

/**
* 发送数据,当前数据不放入到重发队列
* @param datas
* @param nLen
*/
public void sendDataNotPutToList(byte[] datas, int nLen){
synchronized(this){
if (mCallBack != null){
mCallBack.onSendData(datas, nLen);
}
}
}

/**
* 清空重发数据
*/
public void clearDataBuffer(){
synchronized(this){
mListReSend.clear();
mPacketRead = null;
mPacketRead = new ProtocolPacket();
}
}

/**
* 释放资源
*/
public void releaseConnection(){
synchronized(this){
mRun = false;

mListReSend.clear();
}
}

public void removeFromListByCmdID(byte cmdID){
synchronized(this){
ProtocolPacket packet = new ProtocolPacket();
BUFFER_DATA remove = null;
for(BUFFER_DATA buffer: mListReSend){
packet.setRawData(buffer.datas);

if (packet.getmCmd() == cmdID){
remove = buffer;
break;
}
}

if (remove != null)
mListReSend.remove(remove);
}
}

// /**
// * 读数据
// * @param data
// * @param nLen
// */
// public void readData(byte[] data, int nLen){
// for(int i=0; i<nLen; i++){
// if (mPacketRead.setData_(data[i])){
// processPacket(mPacketRead);
// }
// }
// }
//
// /**
// * 发送握手协议
// */
// public void sendHandShake(){
// synchronized(this){
// ProtocolPacket packet = new ProtocolPacket();
//
// packet.setmCmd(ConstValue.DV_HANDSHAKE);
// byte[] params = new byte[1];
// params[0] = 0;
// packet.setmParam(params);
// packet.setmParamLen(1);
//
// byte[] rawDatas = packet.packetData();
//
// sendData(rawDatas, rawDatas.length);
// }
// }


@Override
public void run() {
while (mRun){
synchronized(this){
BUFFER_DATA removeData = null;
for(BUFFER_DATA data: mListReSend){
// 如果500MS没有接收到回应
if (SystemClock.uptimeMillis()-data.lastSendTime >= 1500){

// 如果超过重发次数,则不发。移除列表
if (data.resenTime >= 2){
removeData = data;
break;
}else{
// 重发数据
sendDataNotPutToList(data.datas, data.nLen);
// 更新重发的时间和次数
data.lastSendTime = SystemClock.uptimeMillis();
data.resenTime++;
}
}
}

if (removeData != null){
mListReSend.remove(removeData);
removeData = null;
continue;
}

}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
mRun = false;
break;
}

}
}

}


package com.ubtechinc.base;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


import com.ubtechinc.base.DeviceProcessThread.DeviceProcessThreadCallBack;


import android.bluetooth.BluetoothSocket;
import android.os.SystemClock;
import android.util.Log;


/**
 * 蓝牙客户端处理类
 * 
 * @author juntian018
 * 
 */
public class BlueToothClientHandler extends Thread implements
DeviceProcessThreadCallBack {
static private final String TAG = "BlueToothClientHandler";
/**
* 客户端的MAC地址
*/
private final String mMacAddress;
/**
* 连接的SOCKET
*/
private final BluetoothSocket mBlueToothSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final ClentCallBack mCallBack;


private boolean mRun = true;
private ProtocolPacket mPacketRead;


private long mLastRcvTime;
private long mLastSendTime;


private DeviceProcessThread mProcessThread;


public interface ClentCallBack {
/**
* 客户端收到数据

* @param mac
* @param data
* @param len
*/
void onReceiveData(String mac, byte cmd, byte[] param, int len);
}


public String getmMacAddress() {
return mMacAddress;
}


public void sendData(byte[] datas, int nLen) {
mProcessThread.sendData(datas, nLen);
}


public BlueToothClientHandler(String mac, BluetoothSocket socket,
ClentCallBack callback) {
mMacAddress = mac;
mBlueToothSocket = socket;
mCallBack = callback;


InputStream tmpIn = null;
OutputStream tmpOut = null;


mLastRcvTime = SystemClock.uptimeMillis();
mLastSendTime = mLastRcvTime;


// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}


mmInStream = tmpIn;
mmOutStream = tmpOut;


mPacketRead = new ProtocolPacket();
mProcessThread = new DeviceProcessThread(this);
mProcessThread.start();
}


public void sendXT(byte[] data, int nlen) {
if (SystemClock.uptimeMillis() - mLastSendTime < 1000) {
return;
}


onSendData(data, nlen);
}


/**
* 判断线程是否已经退出

* @return
*/
public boolean tryToReleaseConnection() {
boolean bTimeOut = SystemClock.uptimeMillis() - mLastRcvTime > 6000;
if (mRun == false || this.isAlive() == false || bTimeOut)
return true;


return false;
}


/**
* 释放资源
*/
public void releaseConnection() {
synchronized (this) {
try {
mRun = false;


mProcessThread.releaseConnection();


if (mmInStream != null)
mmInStream.close();


if (mmOutStream != null)
mmOutStream.close();


if (mBlueToothSocket != null)
mBlueToothSocket.close();


} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


@Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;


while (mRun) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
byte[] pTemp = new byte[bytes];
System.arraycopy(buffer, 0, pTemp, 0, bytes);
Log.i("DV_READSTATUS",
"" + ByteHexHelper.bytesToHexString(pTemp));
for (int i = 0; i < bytes; i++) {
if (mPacketRead.setData_(buffer[i])) {
// 一帧数据接收完成
if (mCallBack != null) {
mPacketRead.setmParamLen(mPacketRead.getmParam().length);
mCallBack.onReceiveData(mMacAddress,
mPacketRead.getmCmd(),
mPacketRead.getmParam(),
mPacketRead.getmParamLen());
Log.e("DV_READSTATUS",
"cmd=" + mPacketRead.getmCmd() + " param="
+ mPacketRead.getmParam() + " len="
+ mPacketRead.getmParamLen());
// Log.v("chenlin_blue", mCallBack.toString());
Log.v("chenlin_blue", "rcv");
}


mLastRcvTime = SystemClock.uptimeMillis();


mProcessThread.removeFromListByCmdID(mPacketRead
.getmCmd());
}
}
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
// connectionLost();
mRun = false;
break;
}catch (Exception e) {
mRun = false;
break;
}
}
}


@Override
synchronized public void onSendData(byte[] data, int len) {
try {
mmOutStream.write(data, 0, len);
mLastSendTime = SystemClock.uptimeMillis();
} catch (IOException e) {
releaseConnection();
}catch(Exception e){
releaseConnection();
}
}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Linux C 语言中,可以使用套接字选项 `SO_RCVTIMEO` 和 `SO_SNDTIMEO` 来设置接收和发送超时时间。如果在指定时间内没有收到数据或者数据没有被成功发送,那么就会触发超时重发机制。 具体实现步骤如下: 1. 设置超时时间 使用 `setsockopt()` 函数来设置套接字选项 `SO_RCVTIMEO` 和 `SO_SNDTIMEO`,例如: ``` struct timeval timeout; timeout.tv_sec = 5; // 超时时间为 5 秒 timeout.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { perror("setsockopt"); exit(EXIT_FAILURE); } if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { perror("setsockopt"); exit(EXIT_FAILURE); } ``` 2. 发送数据 使用 `sendto()` 函数发送数据,例如: ``` if (sendto(sockfd, buf, len, 0, (struct sockaddr *)&dest_addr, addrlen) < 0) { perror("sendto"); exit(EXIT_FAILURE); } ``` 3. 接收数据 使用 `recvfrom()` 函数接收数据,例如: ``` if (recvfrom(sockfd, buf, len, 0, (struct sockaddr *)&src_addr, &addrlen) < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) { // 超时,进行重发操作 if (sendto(sockfd, buf, len, 0, (struct sockaddr *)&dest_addr, addrlen) < 0) { perror("sendto"); exit(EXIT_FAILURE); } } else { perror("recvfrom"); exit(EXIT_FAILURE); } } ``` 在上面的代码中,如果 `recvfrom()` 函数返回的错误码是 `EWOULDBLOCK` 或者 `EAGAIN`,那么说明接收超时,此时可以进行重发操作。如果返回的错误码是其他值,那么说明接收出错,需要退出程序。 需要注意的是,超时时间的设置应该根据具体情况来确定,如果设置得太短,会频繁触发重发机制,影响性能;如果设置得太长,会增加数据传输的延迟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值