上篇用sleep 这篇用的是netty时间轮定时器达到类似效果
只改了通用的EchoWrite 辅助类 这个类 换成时间片实现超时重传。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class EchoWrite {
EventExecutor e;
DefaultPromise t;
int times1 = 0;
final Timer timer = new HashedWheelTimer();
public EchoWrite2() {
this.e = new DefaultEventExecutor();
t=new DefaultPromise(this.e);
}

public <T> DefaultPromise echoWrite(String msg, InetSocketAddress add ,Channel c,String attrKey ,T attrValue, int times, int timeoutS) {

c.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8), add));
log.info("发出echo");

log.info("位置4 "+String.valueOf(Thread.currentThread().getId()));
timer.newTimeout(new TimerTask() {
public void run(Timeout timeout) throws Exception {
log.info("位置3 "+String.valueOf(Thread.currentThread().getId()));

AttributeKey<Integer> bechoAttr = AttributeKey.valueOf(attrKey);
Attribute<Integer> bechoA = c.attr(bechoAttr);
times1++;
if (times1 < times) {
bechoA = c.attr(bechoAttr);
if (bechoA.get() == attrValue) {

t.setSuccess(true);
} else {
log.info("发出echo");
c.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8), add));
timer.newTimeout(this, timeoutS, TimeUnit.SECONDS);
}
}
if (times1 == times) {

Exception ex = new Exception("超时没有回应");
t.setFailure(ex);
}
}
}, timeoutS, TimeUnit.SECONDS);

return t;
}
}

这个超时重传在tcp里也可以使用应该。。。不过由于udp传输可靠性没有。可以保证操作的可靠性,还有一定的保活的作用。
这里的times1是不是线程安全。。。。 如果多个线程都要可靠性发数据 那么是不是每个线程都弄个times1变量?会不会存在几个线程用一个EchoWrite对象的情况。

在琢磨琢磨 ,好像attr是线程安全的。