forked from KNEMC/KLALB
479 lines
16 KiB
Java
479 lines
16 KiB
Java
package org.kne.cloud.network.perf;
|
|
|
|
import java.io.IOException;
|
|
import java.net.Inet6Address;
|
|
import java.net.InetAddress;
|
|
import java.nio.channels.UnresolvedAddressException;
|
|
import java.util.Objects;
|
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
import java.util.concurrent.PriorityBlockingQueue;
|
|
import java.util.concurrent.locks.LockSupport;
|
|
|
|
import org.kne.cloud.clock.AdjustedNanoClock;
|
|
import org.kne.cloud.network.MultipurposeSocketAddress;
|
|
import org.kne.cloud.network.SpeedLimiter;
|
|
import org.kne.cloud.network.ThreadTool;
|
|
import org.kne.cloud.network.ipv6.IPv6Packet;
|
|
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
|
import org.kne.cloud.network.klalb.ADDRPacket;
|
|
import org.kne.cloud.network.klalb.ADDRREQPacket;
|
|
import org.kne.cloud.network.klalb.BWINFPacket;
|
|
import org.kne.cloud.network.klalb.IPv6OverKLALBPacket;
|
|
import org.kne.cloud.network.klalb.KLALBPacket;
|
|
import org.kne.cloud.network.klalb.KLALBPacketLink;
|
|
import org.kne.cloud.network.klalb.KLALBUtils;
|
|
import org.kne.cloud.network.klalb.PINGPacket;
|
|
import org.kne.cloud.network.klalb.PONGPacket;
|
|
import org.kne.cloud.network.klalb.VADDRACKPacket;
|
|
import org.kne.cloud.network.klalb.VADDRPacket;
|
|
import org.kne.cloud.network.klalb.VADDRREQPacket;
|
|
import org.kne.cloud.network.monitor.MonitorData;
|
|
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
|
|
|
|
public class Kperf implements Runnable{
|
|
|
|
|
|
|
|
private ConcurrentLinkedQueue<KLALBPacket> IsendDequeList = new ConcurrentLinkedQueue<KLALBPacket>();
|
|
|
|
//private PriorityBlockingQueue<KLALBPacket> sendDequeList = new PriorityBlockingQueue<KLALBPacket>();
|
|
|
|
|
|
private static final boolean debug = true;
|
|
|
|
private static final boolean showpacket = false;
|
|
private volatile AdjustedNanoClock adjnc = new AdjustedNanoClock();
|
|
private MultipurposeSocketAddress targetAddress;
|
|
private MultipurposeSocketAddress bindAddress;
|
|
private volatile boolean connected=false;
|
|
private volatile KLALBPacketLink link;
|
|
private QueueingMonitorDataImpl monitor=new QueueingMonitorDataImpl();
|
|
|
|
private volatile boolean closed = false;
|
|
|
|
private volatile Thread tlock;
|
|
public Kperf(MultipurposeSocketAddress targetAddress,MultipurposeSocketAddress bindAddress) {
|
|
Objects.requireNonNull(targetAddress);
|
|
this.targetAddress=targetAddress;
|
|
this.bindAddress=bindAddress;
|
|
}
|
|
public Kperf(MultipurposeSocketAddress targetAddress) {
|
|
this(targetAddress,new MultipurposeSocketAddress("[::0]:0"));
|
|
}
|
|
public Kperf(KLALBPacketLink link) {
|
|
Objects.requireNonNull(link);
|
|
this.link=link;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SpeedLimiter test = new SpeedLimiter(MIN_SPEED,10000000L);
|
|
|
|
private static long MIN_SPEED=64*1024L;
|
|
private SpeedLimiter congress = new SpeedLimiter(10000000L);
|
|
private long congressSpeed = 0;
|
|
private double loadPercent = 1.01;
|
|
|
|
KLALBPacket testPacket=null;
|
|
//kperf {KLALB_Stream}[2486:1:f189:7589:f1f7:6f5e:b2eb:1]:4564
|
|
//kperf {KLALB_Stream}[2486:1::8888]:4564
|
|
@Override
|
|
public void run() {
|
|
Thread tc = ThreadTool.makeVDaemonThreadIfSupport("测速控制线程", () -> {
|
|
final int wtimes=5;
|
|
System.out.println("测速开始!");
|
|
try {
|
|
long startTime;
|
|
|
|
/*System.out.println("测试1/4:延迟测试");
|
|
test.setLimitspeed(0);
|
|
startTime=System.nanoTime();
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("上传延迟:%.3fms 下载延迟:%.3fms\n", monitor.getOutDelay()/1000000.0,monitor.getInDelay()/1000000.0);
|
|
Thread.sleep(1000);
|
|
}
|
|
System.out.printf("上传延迟 最小:%.3fms 平均:%.3fms 抖动:%.3fms\n",monitor.getOutDelayMin()/1000000.0,monitor.getOutDelayAvg()/1000000.0,monitor.getOutJitter()/1000000.0);
|
|
System.out.printf("下载延迟 最小:%.3fms 平均:%.3fms 抖动:%.3fms\n",monitor.getInDelayMin()/1000000.0,monitor.getInDelayAvg()/1000000.0,monitor.getInJitter()/1000000.0);
|
|
|
|
System.out.println("等待时间"+wtimes+"s");
|
|
Thread.sleep(wtimes*1000);
|
|
|
|
*/
|
|
startTime=System.nanoTime();
|
|
if(targetAddress!=null) {
|
|
System.out.println("测试2/4:下载带宽测试");
|
|
test.setLimitspeed(0);
|
|
testPacket=new TESTNPacket(60000);
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("下载带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getInSpeedAvg()));
|
|
Thread.sleep(1000);
|
|
}
|
|
|
|
System.out.printf("下载带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getInSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getInSpeedMax2()));
|
|
}else {
|
|
System.out.println("测试2/4:上传带宽测试");
|
|
test.setLimitspeed(1000L*1024L*1024L*1024L);
|
|
testPacket=new TESTNPacket(60000);
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("上传带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getOutSpeedAvg()));
|
|
Thread.sleep(1000);
|
|
}
|
|
System.out.printf("上传带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getOutSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getOutSpeedMax2()));
|
|
}
|
|
System.out.println("等待时间"+wtimes+"s");
|
|
Thread.sleep(wtimes*1000);
|
|
|
|
|
|
|
|
startTime=System.nanoTime();
|
|
if(targetAddress!=null) {
|
|
System.out.println("测试3/4:上传带宽测试");
|
|
test.setLimitspeed(1000L*1024L*1024L*1024L);
|
|
testPacket=new TESTNPacket(60000);
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("上传带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getOutSpeedAvg()));
|
|
Thread.sleep(1000);
|
|
}
|
|
System.out.printf("上传带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getOutSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getOutSpeedMax2()));
|
|
|
|
}else {
|
|
System.out.println("测试3/4:下载带宽测试");
|
|
test.setLimitspeed(0);
|
|
testPacket=new TESTNPacket(60000);
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("下载带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getInSpeedAvg()));
|
|
Thread.sleep(1000);
|
|
}
|
|
System.out.printf("下载带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getInSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getInSpeedMax2()));
|
|
}
|
|
|
|
System.out.println("等待时间"+wtimes+"s");
|
|
Thread.sleep(wtimes*1000);
|
|
|
|
startTime=System.nanoTime();
|
|
if(targetAddress!=null) {
|
|
System.out.println("测试2/4:下载包转发率测试");
|
|
test.setLimitspeed(0);
|
|
testPacket=new TEST1Packet();
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("下载包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getInPPS()));
|
|
Thread.sleep(1000);
|
|
}
|
|
}else {
|
|
System.out.println("测试2/4:上传包转发率测试");
|
|
test.setLimitspeed(1000L*1024L*1024L*1024L);
|
|
testPacket=new TEST1Packet();
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("上传包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getOutPPS()));
|
|
Thread.sleep(1000);
|
|
}
|
|
//System.out.printf("上传带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getOutSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getOutSpeedMax2()));
|
|
}
|
|
System.out.println("等待时间"+wtimes+"s");
|
|
Thread.sleep(wtimes*1000);
|
|
|
|
startTime=System.nanoTime();
|
|
if(targetAddress!=null) {
|
|
System.out.println("测试3/4:上传包转发率测试");
|
|
test.setLimitspeed(1000L*1024L*1024L*1024L);
|
|
testPacket=new TEST1Packet();
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("上传包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getOutPPS()));
|
|
Thread.sleep(1000);
|
|
}
|
|
|
|
}else {
|
|
System.out.println("测试3/4:下载包转发率测试");
|
|
test.setLimitspeed(0);
|
|
testPacket=new TEST1Packet();
|
|
for (int i = 0; i < 30; i++) {
|
|
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
|
|
System.out.printf("下载包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getInPPS()));
|
|
Thread.sleep(1000);
|
|
}
|
|
|
|
}
|
|
System.out.println("等待时间"+wtimes+"s");
|
|
Thread.sleep(wtimes*1000);
|
|
|
|
System.out.println("测速结束!");
|
|
|
|
} catch (InterruptedException e) {
|
|
System.out.println("测速被中断!");
|
|
}finally {
|
|
close();
|
|
}
|
|
});
|
|
try {
|
|
monitor.setState(MonitorData.CONNECTING);
|
|
if(link==null)
|
|
link=KLALBUtils.createKLALBPacketLink(bindAddress, targetAddress,false,20000);
|
|
|
|
|
|
link.setSoTimeout(20000);
|
|
|
|
|
|
Thread t = ThreadTool.makeVDaemonThreadIfSupport("测速发送线程", () -> {
|
|
tlock = Thread.currentThread();
|
|
try {
|
|
KLALBPacket kpp = null;
|
|
|
|
while ((!link.isClosed()) && (!closed)) {
|
|
// TimeDebugger tdb=new TimeDebugger();
|
|
// tdb.putTime("start");
|
|
if(checkBandwidthReportTime()) {
|
|
writePacketToKPL(new BWINFPacket(monitor.getOutSpeedAvg2(), monitor.getInSpeedAvg2()));
|
|
}
|
|
if (checkPingTimeSleep()) {
|
|
writePacketToKPL(new PINGPacket(System.nanoTime()));
|
|
|
|
}else {
|
|
KLALBPacket kpip = IsendDequeList.poll();
|
|
if (kpip != null) {
|
|
writePacketToKPL(kpip);
|
|
|
|
}else {
|
|
|
|
KLALBPacket testp=testPacket;
|
|
if (testp!=null&&test.checkTransmit(testp.getLength())) {
|
|
writePacketToKPL(testp);
|
|
|
|
|
|
|
|
}else {
|
|
LockSupport.parkNanos(1000000);
|
|
}
|
|
}
|
|
}
|
|
|
|
Thread.yield();
|
|
}
|
|
} catch (IOException | UnresolvedAddressException e) {
|
|
if (debug)
|
|
e.printStackTrace();
|
|
} finally {
|
|
try {
|
|
link.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
t.start();
|
|
|
|
boolean fst = true;
|
|
while ((!link.isClosed()) && (!closed)) {
|
|
KLALBPacket kpp = readPacketFromKPL();
|
|
|
|
if (kpp == null) {
|
|
break;
|
|
}
|
|
switch (kpp.getType()) {
|
|
case KLALBPacket.PING:
|
|
sendIPacket(new PONGPacket(((PINGPacket) kpp).getTime() ,kpp.getRcvtime(), System.nanoTime()));
|
|
break;
|
|
case KLALBPacket.PONG:
|
|
if (fst) {
|
|
// coll.resetCoolingTime();
|
|
|
|
monitor.setState(MonitorData.ONLINE);
|
|
connected=true;
|
|
if(targetAddress!=null) {
|
|
System.out.println("连接地址"+targetAddress+"成功!");
|
|
}else {
|
|
System.out.println("接受地址"+link.toString()+"连接成功!");
|
|
}
|
|
tc.start();
|
|
fst = false;
|
|
}
|
|
|
|
PONGPacket png = (PONGPacket) kpp;
|
|
long ul = png.getRcvtime() - png.getTimepingsnd()-(png.getTimepongsnd()-png.getTimepingrcv());
|
|
|
|
long DsndDelayFactor0 = png.getTimepingrcv() - png.getTimepingsnd();
|
|
long DrcvDelayFactor0 = png.getRcvtime() - png.getTimepongsnd();
|
|
long DsndDelayFactor;
|
|
long DrcvDelayFactor;
|
|
|
|
adjnc.getLock().lock();
|
|
try {
|
|
adjnc.calibrate(png.getTimepongsnd() + ul / 2 - png.getRcvtime(), ul / 2);
|
|
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
|
|
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
|
|
if (DsndDelayFactor < 0) {
|
|
if (DrcvDelayFactor < 0) {
|
|
|
|
} else {
|
|
adjnc.setDelta(adjnc.getDelta() + DsndDelayFactor);
|
|
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
|
|
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
|
|
}
|
|
} else {
|
|
if (DrcvDelayFactor < 0) {
|
|
adjnc.setDelta(adjnc.getDelta() - DrcvDelayFactor);
|
|
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
|
|
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
|
|
}
|
|
}
|
|
} finally {
|
|
adjnc.getLock().unlock();
|
|
}
|
|
|
|
if (DsndDelayFactor >= 0 && DrcvDelayFactor >= 0) {
|
|
monitor.setOutDelay(DsndDelayFactor);
|
|
monitor.setInDelay(DrcvDelayFactor);
|
|
monitor.setRecentPingNanoTime(png.getTimepingsnd());
|
|
//pingInterval = monitor.getLatencyAvg()+2000000L;
|
|
|
|
//double load = 1 - monitor.getOutDelayMin() / (double) monitor.getOutDelay();
|
|
loadPercent =Math.max( 1.2,0.4);
|
|
}
|
|
|
|
LockSupport.unpark(tlock);
|
|
break;
|
|
case KLALBPacket.BWINF:
|
|
BWINFPacket bwi = (BWINFPacket) kpp;
|
|
if (bwi.getDownSpeed() >= congressSpeed) {
|
|
congressSpeed = bwi.getDownSpeed();
|
|
} else {
|
|
congressSpeed = (congressSpeed * 999 + bwi.getDownSpeed()) / 1000;
|
|
}
|
|
congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * loadPercent)) );
|
|
// System.out.println(congressSpeed);
|
|
break;
|
|
case KLALBPacket.TESTN:
|
|
break;
|
|
}
|
|
Thread.yield();
|
|
}
|
|
} catch (IOException e) {
|
|
if(monitor.getState()==MonitorData.CONNECTING)
|
|
System.out.println("连接目标地址失败!");
|
|
if(debug)
|
|
e.printStackTrace();
|
|
|
|
}finally {
|
|
monitor.setState(MonitorData.OFFLINE);
|
|
if(link!=null) {
|
|
try {
|
|
link.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
tc.interrupt();
|
|
}
|
|
}
|
|
private volatile long time = System.nanoTime();
|
|
private volatile long pingInterval = 10000000L;
|
|
private volatile long pingIntervalSleep = 200000000L;
|
|
|
|
private boolean checkPingTime() {
|
|
long cu = System.nanoTime();
|
|
if (cu - time > pingInterval) {
|
|
time = cu;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
private boolean checkPingTimeSleep() {
|
|
long cu = System.nanoTime();
|
|
if (cu - time > pingIntervalSleep) {
|
|
time = cu;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private volatile long bwtime = System.nanoTime();
|
|
private volatile long bwpingInterval = 10000000L;
|
|
private volatile long bwpingIntervalSleep = 100000000L;
|
|
private boolean checkBandwidthReportTime(){
|
|
long cu = System.nanoTime();
|
|
if (cu - bwtime > bwpingIntervalSleep) {
|
|
bwtime = cu;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public void close() {
|
|
closed = true;
|
|
monitor.setState(MonitorData.OFFLINE);
|
|
try {
|
|
if (link != null)
|
|
link.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
|
|
/*protected void sendPacket(KLALBPacket blk) {
|
|
blk.markJoinqueuetime();
|
|
sendDequeList.add(blk);
|
|
LockSupport.unpark(tlock);
|
|
}*/
|
|
|
|
private void sendIPacket(KLALBPacket blk) {
|
|
IsendDequeList.add(blk);
|
|
LockSupport.unpark(tlock);
|
|
}
|
|
|
|
|
|
private KLALBPacket readPacketFromKPL() throws IOException {
|
|
KLALBPacket packet = link.readKLALBPacket();
|
|
if (showpacket) {
|
|
|
|
System.out.println("RX:" + packet);
|
|
}
|
|
if (packet != null) {
|
|
packet.putTimePassport("received");
|
|
long length=packet.getLength();
|
|
monitor.getInTrafficAL().addAndGet(length);
|
|
monitor.getInPacketCounterAL().incrementAndGet();
|
|
}
|
|
return packet;
|
|
}
|
|
|
|
private void writePacketToKPL(KLALBPacket packet) throws IOException {
|
|
long length=packet.getLength();
|
|
monitor.getOutTrafficAL().addAndGet(length);
|
|
monitor.getOutPacketCounterAL().incrementAndGet();
|
|
link.writeKLALBPacket(packet);
|
|
link.flush();
|
|
packet.putTimePassport("sended");
|
|
packet.printPassport();
|
|
|
|
if (showpacket) {
|
|
System.err.println("TX:" + packet);
|
|
}
|
|
}
|
|
|
|
|
|
public void startPerfing() {
|
|
ThreadTool.makeVThreadIfSupport("测速接收线程" ,this).start();
|
|
}
|
|
}
|