forked from KNEMC/KLALB
TCP连接池功能
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
@@ -1,7 +1,9 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
public class Consts {
|
||||
public static final int BLOCKSIZE=65536;
|
||||
public static final int BLOCKSIZE=32768;
|
||||
public static final long PINGTIMENS=10000000000L;
|
||||
public static final double A = 0.125;
|
||||
public static final int SO_TIMEOUT = 20000;
|
||||
public static final long SN_KEEP = 60000000000L;
|
||||
}
|
||||
|
||||
@@ -4,149 +4,90 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class IOThreadManager {
|
||||
private KLALBCore klc=new KLALBCore(10000);
|
||||
private List<TCPConnection>tcps=new Vector<>();
|
||||
private KLALBCore klc = new KLALBCore(5000);
|
||||
private boolean isopen = true;
|
||||
|
||||
|
||||
private TCPConnection local;
|
||||
|
||||
|
||||
private volatile boolean open=true;
|
||||
public void startLocal() {
|
||||
|
||||
Thread upo=ThreadTool.makeVThreadIfSupport("本地接收线程",()->{
|
||||
public void handleLocal(LocalTCPConnection tc, ServiceElement se,boolean syn) {
|
||||
klc.getLocaltcps().add(tc);
|
||||
try {
|
||||
if(syn) {
|
||||
KLALBBlock sbk=new KLALBBlock();
|
||||
sbk.cuid=tc.getCuid();
|
||||
sbk.number=0;
|
||||
sbk.command=2;
|
||||
sbk.lservice=se.proc;
|
||||
sbk.lipport=se.ipport;
|
||||
klc.submitDataBlockNoDelay(sbk);
|
||||
}
|
||||
Thread ls = ThreadTool.makeVThreadIfSupport("本地发送线程", () -> {
|
||||
|
||||
while(true) {
|
||||
byte[]b=new byte[Consts.BLOCKSIZE];
|
||||
int size=local.getDin().read(b);
|
||||
if(size==-1)
|
||||
break;
|
||||
klc.packDataBlock(b,size);
|
||||
}
|
||||
klc.waitForRemote();
|
||||
}catch(InterruptedException s) {
|
||||
}catch(SocketException se) {
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
closeRemote();
|
||||
}
|
||||
});
|
||||
Thread downo=ThreadTool.makeVThreadIfSupport("本地发送线程",()->{
|
||||
try{
|
||||
while(true) {
|
||||
Thread lr = ThreadTool.makeVThreadIfSupport("本地接收线程", () -> {
|
||||
|
||||
local.getDout().write(klc.unpackDataBlock());
|
||||
local.getDout().flush();
|
||||
}
|
||||
}catch(InterruptedException s) {
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
}
|
||||
});
|
||||
upo.start();
|
||||
downo.start();
|
||||
}
|
||||
public void handleSocket(TCPConnection s) throws IOException {
|
||||
tcps.add(s);
|
||||
try {
|
||||
Thread up=ThreadTool.makeVThreadIfSupport("远程发送线程",()->{
|
||||
try{
|
||||
while(true) {
|
||||
if(s.getTunnel().getName().contains("Openfrp")) {
|
||||
klc.sendDataBlockControlOnly(s);
|
||||
}else {
|
||||
klc.sendDataBlock(s);
|
||||
}
|
||||
}
|
||||
}catch(InterruptedException s1) {
|
||||
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
Thread down=ThreadTool.makeVThreadIfSupport("远程接收线程",()->{
|
||||
try{
|
||||
while(true) {
|
||||
klc.receiveDataBlock(s);
|
||||
}
|
||||
}catch(InterruptedException s1) {
|
||||
|
||||
}catch(Exception e) {
|
||||
up.interrupt();
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
up.start();
|
||||
down.start();
|
||||
try {
|
||||
down.join();
|
||||
ls.start();
|
||||
lr.start();
|
||||
ls.join();
|
||||
lr.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
tcps.remove(s);
|
||||
klc.getLocaltcps().remove(tc);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeRemote() {
|
||||
open=false;
|
||||
|
||||
for (int i = 0; i < tcps.size(); i++) {
|
||||
TCPConnection tll=tcps.get(i);
|
||||
tll.close();
|
||||
}
|
||||
klc.closeRemote();
|
||||
}
|
||||
|
||||
public void closeLocal() {
|
||||
open=false;
|
||||
local.close();
|
||||
klc.closeLocal();
|
||||
}
|
||||
|
||||
public TCPConnection getLocal() {
|
||||
return local;
|
||||
}
|
||||
public void setLocal(TCPConnection local) {
|
||||
this.local = local;
|
||||
}
|
||||
/*
|
||||
public void closeALL() {
|
||||
open=false;
|
||||
|
||||
for (int i = 0; i < tcps.size(); i++) {
|
||||
TCPConnection tll=tcps.get(i);
|
||||
tll.close();
|
||||
}
|
||||
klc.closeRemote();
|
||||
klc.closeLocal();
|
||||
public void handleRemote(RemoteTCPConnection tc) {
|
||||
klc.getRemotetcps().add(tc);
|
||||
try {
|
||||
in.close();
|
||||
Thread rs = ThreadTool.makeVThreadIfSupport("远程发送线程", () -> {
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
klc.remoteSend(tc);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
Thread rr = ThreadTool.makeVThreadIfSupport("远程接收线程", () -> {
|
||||
try {
|
||||
out.close();
|
||||
while (true) {
|
||||
klc.remoteReceive(tc);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
rs.start();
|
||||
rr.start();
|
||||
rs.join();
|
||||
rr.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
klc.getRemotetcps().remove(tc);
|
||||
}
|
||||
*/
|
||||
public List<TCPConnection> getTcps() {
|
||||
return tcps;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
isopen = false;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open;
|
||||
return isopen;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,50 +2,58 @@ package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
|
||||
public class KLALBBlock {
|
||||
volatile byte[]data;
|
||||
volatile int size;
|
||||
volatile long number;
|
||||
private static AtomicLong sng=new AtomicLong(0);
|
||||
|
||||
public long sn;//每个数据包的唯一编号
|
||||
public UUID cuid;//用于识别数据包的stream ID号
|
||||
public long number;//数据包的编号,用于排序
|
||||
public byte[]data;//数据内容
|
||||
public int command;//功能标记 0=PING 1=PONG 2=SYN 3=RST
|
||||
public long pingtime;//PING计时器
|
||||
|
||||
public String lservice;
|
||||
public IPPort lipport;
|
||||
|
||||
|
||||
|
||||
volatile long time=-1;
|
||||
volatile TCPConnection connect;
|
||||
public KLALBBlock(byte[] b, int size,long number) {
|
||||
data=b;
|
||||
this.size=size;
|
||||
this.number=number;
|
||||
}
|
||||
public KLALBBlock() {
|
||||
// TODO 自动生成的构造函数存根
|
||||
sn=sng.getAndIncrement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.append(cuid);
|
||||
sb.append(' ');
|
||||
if(number>0) {
|
||||
return "DATA"+number+":"+size;
|
||||
}else if(number==0){
|
||||
return "PING";
|
||||
}else if(number==Long.MIN_VALUE){
|
||||
return "PONG";
|
||||
sb.append("DATA").append(number).append(':').append(data.length);
|
||||
}else if(number<0) {
|
||||
sb.append("ACK").append(-number);
|
||||
}else {
|
||||
return "ACK"+(-number);
|
||||
switch(command) {
|
||||
case 0:
|
||||
sb.append("PING");
|
||||
break;
|
||||
case 1:
|
||||
sb.append("PONG");
|
||||
break;
|
||||
case 2:
|
||||
sb.append("SYN:").append(lservice).append(" ").append(lipport);
|
||||
break;
|
||||
case 3:
|
||||
sb.append("RST");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(number);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
KLALBBlock other = (KLALBBlock) obj;
|
||||
return number == other.number;
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
@@ -21,111 +22,68 @@ import org.kne.cloud.network.mport.ServiceElement;
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class KLALBClient {
|
||||
private static Object olock=new Object();
|
||||
static {
|
||||
new Thread(()->{
|
||||
while(true) {
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
synchronized(olock) {
|
||||
olock.notifyAll();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
UUID suid=UUID.randomUUID();
|
||||
IOThreadManager iom=new IOThreadManager();
|
||||
private List<Tunnel> tls=new ArrayList<>();
|
||||
private TCPListener tcpl;
|
||||
private ServiceElement sel;
|
||||
|
||||
public void runProtocol(IOThreadManager kcp, UUID uid) {
|
||||
AtomicBoolean b=new AtomicBoolean(true);
|
||||
AtomicInteger aig=new AtomicInteger(0);
|
||||
for (int i = 0; i < tls.size(); i++) {
|
||||
Tunnel tll=tls.get(i);
|
||||
ThreadTool.makeVThreadIfSupport("隧道监视线程",()->{
|
||||
while (kcp.isOpen()) {
|
||||
|
||||
|
||||
public void open(int port) throws IOException {
|
||||
tcpl=new TCPListener(port);
|
||||
tcpl.setCon((s)->{
|
||||
LocalTCPConnection tcc = null;
|
||||
try {
|
||||
TCPConnection tc=new TCPConnection(tll);
|
||||
tc.getDout().writeShort(59649);
|
||||
tc.getDout().write(1);
|
||||
|
||||
tc.getDout().writeUTF(sel.ipport.getIp().getHostAddress());
|
||||
tc.getDout().writeInt(sel.ipport.getPort());
|
||||
tc.getDout().writeUTF(sel.proc);
|
||||
|
||||
tc.getDout().writeUTF(tll.getName());
|
||||
tc.getDout().writeUTF(tll.getIp());
|
||||
tc.getDout().writeInt(tll.getPort());
|
||||
tc.getDout().writeLong(uid.getMostSignificantBits());
|
||||
tc.getDout().writeLong(uid.getLeastSignificantBits());
|
||||
tc.getDout().flush();
|
||||
aig.incrementAndGet();
|
||||
System.out.println("隧道"+tll+"已连接,可用线路数量:"+ (kcp.getTcps().size()+1));
|
||||
try {
|
||||
kcp.handleSocket(tc);
|
||||
|
||||
tcc = new LocalTCPConnection(s);
|
||||
System.out.println("TCP:"+tcc.getCuid()+"已连接");
|
||||
iom.handleLocal(tcc,sel,true);
|
||||
System.out.println("TCP:"+tcc.getCuid()+"已关闭");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(tcc!=null) {
|
||||
tcc.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
tcpl.open();
|
||||
for (int i = 0; i < tls.size(); i++) {
|
||||
Tunnel tll=tls.get(i);
|
||||
ThreadTool.makeVThreadIfSupport("隧道监视线程", ()->{
|
||||
RemoteTCPConnection tc=null;
|
||||
while(iom.isOpen()) {
|
||||
try {
|
||||
tc=new RemoteTCPConnection(tll);
|
||||
tc.getDout().writeShort(59649);
|
||||
tc.getDout().write(1);
|
||||
tc.getDout().writeUTF(tll.getName());
|
||||
tc.getDout().writeUTF(tll.getIp());
|
||||
tc.getDout().writeInt(tll.getPort());
|
||||
tc.getDout().writeLong(suid.getMostSignificantBits());
|
||||
tc.getDout().writeLong(suid.getLeastSignificantBits());
|
||||
tc.getDout().flush();
|
||||
System.out.println(tll+":连接成功");
|
||||
iom.handleRemote(tc);
|
||||
System.out.println(tll+":连接断开");
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}catch(ConnectException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(tc!=null)
|
||||
tc.close();
|
||||
}
|
||||
int n=kcp.getTcps().size();
|
||||
System.out.println("隧道"+tll+"已断开,可用线路数量:"+ n);
|
||||
if(n<=0) {
|
||||
kcp.closeRemote();
|
||||
kcp.closeLocal();
|
||||
System.out.println("连接已断开");
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if(aig.get()<=0) {
|
||||
kcp.closeRemote();
|
||||
kcp.closeLocal();
|
||||
if(b.get()) {
|
||||
System.out.println("隧道连接失败");
|
||||
b.set(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(olock) {
|
||||
try {
|
||||
olock.wait();
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
public void open(int port) throws IOException {
|
||||
tcpl=new TCPListener(port);
|
||||
tcpl.setCon((s)->{
|
||||
IOThreadManager kcp=new IOThreadManager();
|
||||
UUID uid=UUID.randomUUID();
|
||||
try {
|
||||
kcp.setLocal(new TCPConnection(null, s));
|
||||
kcp.startLocal();
|
||||
runProtocol(kcp,uid);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
tcpl.open();
|
||||
}
|
||||
public List<Tunnel> getTls() {
|
||||
return tls;
|
||||
@@ -139,7 +97,7 @@ public class KLALBClient {
|
||||
IPPort u=new IPPort(ipport);
|
||||
TCPConnection tcpc=null;
|
||||
try {
|
||||
tcpc=new TCPConnection(null, new Socket(u.getIp(),u.getPort()));
|
||||
tcpc=new RemoteTCPConnection(null, new Socket(u.getIp(),u.getPort()));
|
||||
tcpc.getDout().writeShort(59649);
|
||||
tcpc.getDout().write(0);
|
||||
tcpc.getDout().flush();
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.kne.ui.XFrame;
|
||||
|
||||
public class KLALBClientGUI extends XFrame{
|
||||
public KLALBClientGUI() {
|
||||
setResizable(false);
|
||||
setTitleColor(new Color(0,0,255,128));
|
||||
getContentPane().setBackground(new Color(128,128,255,128));
|
||||
setTitle("KNE云网络负载均衡客户端");
|
||||
setSize(600,370);
|
||||
setLocationRelativeTo(null);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new KLALBClientGUI();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,9 +13,11 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
@@ -25,294 +27,154 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class KLALBCore {
|
||||
private volatile long inputcount = 1;
|
||||
private volatile long outputcount = 1;
|
||||
private Set<KLALBBlock> inputcache = Collections.synchronizedSet(new HashSet<>());
|
||||
private List<KLALBBlock> outputcache = new Vector<>();
|
||||
|
||||
private BlockingQueue<KLALBBlock> ackp=new LinkedBlockingQueue<>();
|
||||
private BlockingQueue<KLALBBlock> ackq=new LinkedBlockingQueue<>();
|
||||
private volatile boolean inlocal=true;
|
||||
|
||||
private volatile boolean closeremote = false;
|
||||
private volatile boolean closelocal = false;
|
||||
|
||||
private static final UUID ZERO_UUID=new UUID(0,0);
|
||||
private volatile int cacheblocks;
|
||||
|
||||
|
||||
private List<LocalTCPConnection> localtcps = new Vector<>();
|
||||
private List<RemoteTCPConnection> remotetcps = new Vector<>();
|
||||
private Predicate<KLALBBlock>acceptSYN;
|
||||
|
||||
|
||||
private volatile long rsntime=System.nanoTime();
|
||||
private Set<SN> rsns=Collections.synchronizedSet(new HashSet<SN>());
|
||||
private static class SN{
|
||||
volatile long sn;
|
||||
volatile long time;
|
||||
public SN(long sn) {
|
||||
super();
|
||||
this.sn = sn;
|
||||
this.time=System.nanoTime();
|
||||
}
|
||||
public boolean isVaild() {
|
||||
return System.nanoTime()-time<=Consts.SN_KEEP;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(sn);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
SN other = (SN) obj;
|
||||
return sn == other.sn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Predicate<KLALBBlock> getAcceptSYN() {
|
||||
return acceptSYN;
|
||||
}
|
||||
|
||||
public void setAcceptSYN(Predicate<KLALBBlock> acceptSYN) {
|
||||
this.acceptSYN = acceptSYN;
|
||||
}
|
||||
|
||||
public List<LocalTCPConnection> getLocaltcps() {
|
||||
return localtcps;
|
||||
}
|
||||
|
||||
public List<RemoteTCPConnection> getRemotetcps() {
|
||||
return remotetcps;
|
||||
}
|
||||
|
||||
public KLALBCore(int cachesize) {
|
||||
cacheblocks=cachesize;
|
||||
}
|
||||
|
||||
public void packDataBlock(byte[] b, int size) throws InterruptedException {
|
||||
|
||||
if (closelocal)
|
||||
throw new InterruptedException();
|
||||
while (!outputcache.isEmpty()&&(outputcount-outputcache.get(0).number>cacheblocks)) {
|
||||
if (closelocal)
|
||||
Thread.currentThread().interrupt();
|
||||
public void remoteSend(RemoteTCPConnection tc) throws InterruptedException, IOException {
|
||||
for(;;) {
|
||||
if(tc.checkPingTime()) {
|
||||
KLALBBlock pdb=new KLALBBlock();
|
||||
pdb.cuid=ZERO_UUID;
|
||||
pdb.number=0;
|
||||
pdb.command=0;
|
||||
pdb.pingtime=System.nanoTime();
|
||||
tc.sendBlock(pdb);
|
||||
}
|
||||
if(!tc.getSendDeque().isEmpty())
|
||||
break;
|
||||
Thread.sleep(1);
|
||||
}
|
||||
outputcache.add(new KLALBBlock(b, size, outputcount++));
|
||||
|
||||
}
|
||||
|
||||
public byte[] unpackDataBlock() throws InterruptedException {
|
||||
inlocal=false;
|
||||
try {
|
||||
if (closelocal)
|
||||
throw new InterruptedException();
|
||||
byte[] b = null;
|
||||
while (true) {
|
||||
synchronized (inputcache) {
|
||||
Iterator<KLALBBlock> klb = inputcache.iterator();
|
||||
while (klb.hasNext()) {
|
||||
KLALBBlock klalbBlock = (KLALBBlock) klb.next();
|
||||
if (klalbBlock.number < inputcount) {
|
||||
klb.remove();
|
||||
} else if (klalbBlock.number == inputcount) {
|
||||
b = klalbBlock.data;
|
||||
klb.remove();
|
||||
KLALBBlock k=tc.getSendDeque().poll();
|
||||
if(k!=null) {
|
||||
tc.sendBlock(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b != null) {
|
||||
System.out.println("\tSORT:"+inputcount+" " + inputcache.size());
|
||||
inputcount++;
|
||||
return b;
|
||||
}
|
||||
if (closelocal)
|
||||
Thread.currentThread().interrupt();
|
||||
Thread.sleep(1);
|
||||
//System.err.println(inputcount);
|
||||
|
||||
}
|
||||
}finally {
|
||||
inlocal=true;
|
||||
}
|
||||
}
|
||||
|
||||
private void makeAck(KLALBBlock klalbBlock) {
|
||||
KLALBBlock klb1=new KLALBBlock(null, 0, -klalbBlock.number);
|
||||
klb1.time=klalbBlock.time;
|
||||
ackq.add(klb1);
|
||||
if(ackp.size()<100) {
|
||||
KLALBBlock klb2=new KLALBBlock(null, 0, -klalbBlock.number);
|
||||
klb2.time=klalbBlock.time;
|
||||
ackp.add(klb2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sendDataBlock(TCPConnection out) throws IOException, InterruptedException {
|
||||
if (closeremote)
|
||||
throw new InterruptedException();
|
||||
//BlockingQueue<KLALBBlock> bqk=acks.get(out);
|
||||
while (ackq.isEmpty()&& outputcache.isEmpty()) {
|
||||
if (closeremote)
|
||||
Thread.currentThread().interrupt();
|
||||
Thread.sleep(1);
|
||||
if(out.checkPingTime()) {
|
||||
send0(out, new KLALBBlock(null,0 , 0));
|
||||
}
|
||||
}
|
||||
KLALBBlock klb=ackq.poll();
|
||||
if(klb!=null) {
|
||||
send0(out, klb);
|
||||
}else {
|
||||
KLALBBlock ks = null;
|
||||
synchronized (outputcache) {
|
||||
for (int i = 0; i < outputcache.size(); i++) {
|
||||
|
||||
KLALBBlock kd = outputcache.get(i);
|
||||
if (kd.connect == null) {
|
||||
kd.time = System.nanoTime();
|
||||
kd.connect = out;
|
||||
ks = kd;
|
||||
} else {
|
||||
if (kd.connect.isOpen()) {
|
||||
long timex = (System.nanoTime() - kd.time) / 1000000;
|
||||
if (timex > 100+1000*i) {
|
||||
kd.time = System.nanoTime();
|
||||
kd.connect = out;
|
||||
ks = kd;
|
||||
System.out.println("³¬Ê±ÖØ´«£º"+kd);
|
||||
}
|
||||
} else {
|
||||
kd.time = System.nanoTime();
|
||||
kd.connect = out;
|
||||
ks = kd;
|
||||
System.out.println("µôÏßÖØ´«£º"+kd);
|
||||
}
|
||||
}
|
||||
if (ks != null) {
|
||||
public void remoteReceive(RemoteTCPConnection tc) throws IOException {
|
||||
KLALBBlock brc=null;
|
||||
for(;;) {
|
||||
brc=tc.receiveBlock();
|
||||
SN s=new SN(brc.sn);
|
||||
synchronized (rsns) {
|
||||
if(!rsns.contains(s)) {
|
||||
rsns.add(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ks != null) {
|
||||
send0(out, ks);
|
||||
ks.time = System.nanoTime();
|
||||
synchronized (rsns) {
|
||||
long ctime=System.nanoTime();
|
||||
if(ctime-rsntime>10000000000L) {
|
||||
rsntime=ctime;
|
||||
for (Iterator<SN> iterator = rsns.iterator(); iterator.hasNext();) {
|
||||
SN sn = (SN) iterator.next();
|
||||
if(!sn.isVaild()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(brc.cuid.equals(ZERO_UUID)) {
|
||||
if(brc.number==0) {
|
||||
if(brc.command==0) {
|
||||
KLALBBlock pdb=new KLALBBlock();
|
||||
pdb.cuid=ZERO_UUID;
|
||||
pdb.number=0;
|
||||
pdb.command=1;
|
||||
pdb.pingtime=brc.pingtime;
|
||||
tc.getSendDeque().addFirst(pdb);
|
||||
}else if(brc.command==1) {
|
||||
long cur=System.nanoTime();
|
||||
long delay=(cur-brc.pingtime)/2;
|
||||
tc.setDelay(delay);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
Thread.sleep(1);
|
||||
if(brc.number==0) {
|
||||
if(brc.command==0) {
|
||||
}else if(brc.command==1) {
|
||||
}else if(brc.command==2) {
|
||||
if(acceptSYN==null||!acceptSYN.test(brc)) {
|
||||
KLALBBlock rst=new KLALBBlock();
|
||||
rst.cuid=brc.cuid;
|
||||
rst.number=0;
|
||||
rst.command=3;
|
||||
submitDataBlockNoDelay(rst);
|
||||
}
|
||||
}else if(brc.command==3) {
|
||||
}
|
||||
}
|
||||
|
||||
if(out.checkPingTime()) {
|
||||
send0(out, new KLALBBlock(null,0 , 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void sendDataBlockControlOnly(TCPConnection out) throws IOException, InterruptedException {
|
||||
if (closeremote)
|
||||
throw new InterruptedException();
|
||||
//BlockingQueue<KLALBBlock> bqk=acks.get(out);
|
||||
while (ackp.isEmpty()) {
|
||||
if (closeremote)
|
||||
Thread.currentThread().interrupt();
|
||||
Thread.sleep(1);
|
||||
if(out.checkPingTime()) {
|
||||
send0(out, new KLALBBlock(null,0 , 0));
|
||||
}
|
||||
}
|
||||
KLALBBlock klb=ackp.poll();
|
||||
if(klb!=null) {
|
||||
send0(out, klb);
|
||||
//System.out.println(klb+" "+ackp.size());
|
||||
}
|
||||
if(out.checkPingTime()) {
|
||||
send0(out, new KLALBBlock(null,0 , 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveDataBlock(TCPConnection in) throws IOException, InterruptedException {
|
||||
if (closeremote)
|
||||
throw new InterruptedException();
|
||||
KLALBBlock x = receive0(in);
|
||||
long rect=System.nanoTime();
|
||||
if (x.number > 0) {
|
||||
|
||||
/*BlockingQueue<KLALBBlock> bq=acks.get(in);
|
||||
if(bq==null) {
|
||||
BlockingQueue<KLALBBlock> bqt=new LinkedBlockingQueue<>();
|
||||
bqt.add(klb);
|
||||
acks.put(in,bqt);
|
||||
}else {
|
||||
acks.get(in).add(klb);
|
||||
}*/
|
||||
|
||||
if (x.number >= inputcount) {
|
||||
|
||||
while(inputcache.size()>(2*cacheblocks)&&inlocal) {
|
||||
if (closeremote)
|
||||
Thread.currentThread().interrupt();
|
||||
Thread.sleep(1);
|
||||
}
|
||||
|
||||
inputcache.add(x);
|
||||
}
|
||||
makeAck(x);
|
||||
|
||||
} else if(x.number==0) {
|
||||
ThreadTool.makeVThreadIfSupport("TACK", ()->{
|
||||
try {
|
||||
KLALBBlock klk=new KLALBBlock(null,0,Long.MIN_VALUE);
|
||||
long st=System.nanoTime();
|
||||
long tw=st-rect;
|
||||
klk.time=x.time+tw;
|
||||
send0(in, klk);
|
||||
} catch (IOException e) {
|
||||
}finally {
|
||||
}
|
||||
}).start();
|
||||
}else if(x.number==Long.MIN_VALUE){
|
||||
//System.out.println("PING:"+(System.nanoTime()-x.time)/2000000);
|
||||
long del=(System.nanoTime()-x.time)/2;
|
||||
in.setDelay(del);
|
||||
}else{
|
||||
long v = -x.number;
|
||||
outputcache.removeIf((b) -> {
|
||||
return b.number == v;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void send0(TCPConnection tcp, KLALBBlock kd) throws IOException {
|
||||
DataOutputStream out=tcp.getDout();
|
||||
synchronized (out) {
|
||||
|
||||
out.writeLong(kd.number);
|
||||
if (kd.number > 0) {
|
||||
out.writeLong(System.nanoTime());
|
||||
out.writeInt(kd.size);
|
||||
out.write(kd.data, 0, kd.size);
|
||||
}else if(kd.number==0){
|
||||
out.writeLong(System.nanoTime());
|
||||
}else if(kd.number==Long.MIN_VALUE) {
|
||||
out.writeLong(kd.time);
|
||||
}else {
|
||||
out.writeLong(kd.time);
|
||||
}
|
||||
out.flush();
|
||||
public void submitDataBlock(KLALBBlock kb) {
|
||||
|
||||
}
|
||||
System.out.println(tcp.getTunnel().getName()+" SEND:" + kd);
|
||||
}
|
||||
|
||||
private KLALBBlock receive0(TCPConnection tcp) throws IOException {
|
||||
KLALBBlock kb = new KLALBBlock();
|
||||
DataInputStream in=tcp.getDin();
|
||||
synchronized (in) {
|
||||
|
||||
kb.number = in.readLong();
|
||||
if (kb.number > 0) {
|
||||
kb.time=in.readLong();
|
||||
kb.size = in.readInt();
|
||||
if(kb.size<0||kb.size>65536) {
|
||||
throw new StreamCorruptedException(tcp+"block size error:"+kb.size);
|
||||
}
|
||||
kb.data = new byte[kb.size];
|
||||
in.readFully(kb.data);
|
||||
}else if(kb.number==0){
|
||||
kb.time=in.readLong();
|
||||
}else if(kb.number==Long.MIN_VALUE) {
|
||||
kb.time=in.readLong();
|
||||
}else {
|
||||
kb.time=in.readLong();
|
||||
//tcp.nextRTT(System.nanoTime()-kb.time);
|
||||
}
|
||||
}
|
||||
System.out.println(tcp.getTunnel().getName()+" RECEIVE:" + kb);
|
||||
return kb;
|
||||
}
|
||||
|
||||
public void closeRemote() {
|
||||
closeremote = true;
|
||||
outputcache.clear();
|
||||
}
|
||||
public void closeLocal() {
|
||||
closelocal = true;
|
||||
inputcache.clear();
|
||||
}
|
||||
|
||||
|
||||
public void waitForRemote() {
|
||||
while(outputcache.size()>0) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void waitForLocal() {
|
||||
while(inputcache.size()>0) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
public void submitDataBlockNoDelay(KLALBBlock kb) {
|
||||
synchronized (remotetcps) {
|
||||
for (Iterator<RemoteTCPConnection> iterator = remotetcps.iterator(); iterator.hasNext();) {
|
||||
RemoteTCPConnection rmt = (RemoteTCPConnection) iterator.next();
|
||||
rmt.getSendDeque().addFirst(kb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,15 @@ import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
public class KLALBServer {
|
||||
|
||||
WeakHashMap<UUID, IOThreadManager> whm=new WeakHashMap<>();
|
||||
public KLALBServer(int port, Map<String,ServiceElement> services,List<Tunnel> tunnels) throws IOException {
|
||||
TCPListener tcpl=new TCPListener(port);
|
||||
tcpl.setCon((s)->{
|
||||
TCPConnection tcc=null;
|
||||
RemoteTCPConnection tcc=null;
|
||||
try {
|
||||
//s.setSoTimeout(10000);
|
||||
tcc=new TCPConnection(null,s);
|
||||
tcc=new RemoteTCPConnection(null,s);
|
||||
DataInputStream din=tcc.getDin();
|
||||
int val=din.readShort()&0xffff;
|
||||
if(val!=59649) {
|
||||
@@ -52,16 +53,6 @@ public class KLALBServer {
|
||||
return;
|
||||
}
|
||||
|
||||
String lip=din.readUTF();
|
||||
int lport=din.readInt();
|
||||
String lname=din.readUTF();
|
||||
ServiceElement eas=services.get(lname);
|
||||
System.out.println(eas);
|
||||
|
||||
if(eas==null||(!eas.ipport.equals(new IPPort(lip, lport)))){
|
||||
return;
|
||||
}
|
||||
|
||||
String name = din.readUTF();
|
||||
String ip = din.readUTF();
|
||||
int portx=din.readInt();
|
||||
@@ -69,28 +60,16 @@ public class KLALBServer {
|
||||
tcc.setTunnel(tll);
|
||||
|
||||
UUID uid=new UUID(din.readLong(),din.readLong());
|
||||
|
||||
System.out.println(new IPPort((InetSocketAddress)s.getRemoteSocketAddress())+"->"+tll.getIpport()+"->"+eas.ipport);
|
||||
IOThreadManager nx = null;
|
||||
synchronized (tcpl) {
|
||||
if(whm.containsKey(uid)) {
|
||||
nx=whm.get(uid);
|
||||
}else {
|
||||
nx=new IOThreadManager();
|
||||
Socket soc=new Socket(eas.ipport.getIp(),eas.ipport.getPort());
|
||||
nx.setLocal(new TCPConnection(null, soc));
|
||||
nx.startLocal();
|
||||
whm.put(uid, nx);
|
||||
|
||||
}
|
||||
nx.handleSocket(tcc);
|
||||
int n=nx.getTcps().size();
|
||||
System.out.println(nx.getTcps());
|
||||
if(n<=0) {
|
||||
nx.closeLocal();
|
||||
System.out.println("连接已关闭");
|
||||
}
|
||||
}catch(ConnectException e) {
|
||||
System.out.println("连接本地服务失败,请检查你的服务程序");
|
||||
nx.handleRemote(tcc);
|
||||
}catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LocalTCPConnection extends TCPConnection {
|
||||
private UUID cuid;
|
||||
public LocalTCPConnection(Socket s) throws IOException {
|
||||
super(s);
|
||||
cuid=UUID.randomUUID();
|
||||
}
|
||||
public LocalTCPConnection(Socket s,UUID uid) throws IOException {
|
||||
super(s);
|
||||
cuid=uid;
|
||||
}
|
||||
public UUID getCuid() {
|
||||
return cuid;
|
||||
}
|
||||
public void setCuid(UUID cuid) {
|
||||
this.cuid = cuid;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
|
||||
public class RemoteTCPConnection extends TCPConnection {
|
||||
|
||||
public RemoteTCPConnection(Tunnel t) throws UnknownHostException, IOException {
|
||||
this(t,t.connectClientSocket());
|
||||
}
|
||||
public RemoteTCPConnection(Tunnel t,Socket s) throws UnknownHostException, IOException {
|
||||
super(s);
|
||||
this.tunnel=t;
|
||||
s.setSoTimeout(Consts.SO_TIMEOUT);
|
||||
}
|
||||
private long delay=-1;
|
||||
private Tunnel tunnel;
|
||||
public Tunnel getTunnel() {
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
public void setTunnel(Tunnel tunnel) {
|
||||
this.tunnel = tunnel;
|
||||
}
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public void setDelay(long delay) {
|
||||
this.delay = delay;
|
||||
if(tunnel!=null) {
|
||||
tunnel.setDelay(delay);
|
||||
}
|
||||
|
||||
}
|
||||
public void sendBlock(KLALBBlock data) throws IOException {
|
||||
dout.writeLong(data.sn);
|
||||
dout.writeLong(data.cuid.getMostSignificantBits());
|
||||
dout.writeLong(data.cuid.getLeastSignificantBits());
|
||||
dout.writeLong(data.number);
|
||||
if(data.number>0) {
|
||||
dout.writeInt(data.data.length);
|
||||
dout.write(data.data);
|
||||
}else if(data.number==0) {
|
||||
dout.write(data.command);
|
||||
switch(data.command) {
|
||||
case 0:
|
||||
case 1:
|
||||
dout.writeLong(data.pingtime);
|
||||
break;
|
||||
case 2:
|
||||
dout.writeUTF(data.lservice);
|
||||
dout.writeUTF(data.lipport.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dout.flush();
|
||||
|
||||
System.out.println("SEND:"+data);
|
||||
}
|
||||
public KLALBBlock receiveBlock() throws IOException {
|
||||
KLALBBlock klb=new KLALBBlock();
|
||||
klb.sn=din.readLong();
|
||||
klb.cuid=new UUID(din.readLong(), din.readLong());
|
||||
klb.number=din.readLong();
|
||||
if(klb.number>0) {
|
||||
int size=din.readInt();
|
||||
byte[]d=new byte[size];
|
||||
din.readFully(d);
|
||||
klb.data=d;
|
||||
}else if(klb.number==0) {
|
||||
klb.command=din.read();
|
||||
switch(klb.command) {
|
||||
case 0:
|
||||
case 1:
|
||||
klb.pingtime=din.readLong();
|
||||
break;
|
||||
case 2:
|
||||
klb.lservice=din.readUTF();
|
||||
klb.lipport=new IPPort(din.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("RECEIVE:"+klb);
|
||||
return klb;
|
||||
}
|
||||
|
||||
private volatile long time=System.nanoTime();
|
||||
public boolean checkPingTime() {
|
||||
long cu=System.nanoTime();
|
||||
if(cu-time>Consts.PINGTIMENS) {
|
||||
time=cu;
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private BlockingDeque<KLALBBlock>sendDeque=new LinkedBlockingDeque<>();
|
||||
public BlockingDeque<KLALBBlock> getSendDeque() {
|
||||
return sendDeque;
|
||||
}
|
||||
}
|
||||
@@ -8,28 +8,16 @@ import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class TCPConnection {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TCPConnection [tunnel=" + tunnel + ", connect=" + connect + ", delay=" + delay + "]";
|
||||
}
|
||||
|
||||
private Tunnel tunnel;
|
||||
|
||||
private Socket connect;
|
||||
private DataInputStream din;
|
||||
|
||||
public Tunnel getTunnel() {
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
private DataOutputStream dout;
|
||||
private long delay=-1;
|
||||
|
||||
/*public Socket getConnect() {
|
||||
return connect;
|
||||
}*/
|
||||
protected DataInputStream din;
|
||||
protected DataOutputStream dout;
|
||||
|
||||
public DataInputStream getDin() {
|
||||
return din;
|
||||
@@ -61,44 +49,19 @@ public class TCPConnection {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(tunnel!=null&&connect!=null)
|
||||
tunnel.getCCount().decrementAndGet();
|
||||
connect = null;
|
||||
}
|
||||
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public void setDelay(long delay) {
|
||||
this.delay = delay;
|
||||
if(tunnel!=null) {
|
||||
tunnel.setDelay(delay);
|
||||
}
|
||||
if(connect!=null) {
|
||||
try {
|
||||
connect.setSoTimeout(10000);
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTunnel(Tunnel tunnel) {
|
||||
this.tunnel = tunnel;
|
||||
}
|
||||
|
||||
public TCPConnection(Tunnel t) throws UnknownHostException, IOException {
|
||||
this(t, t.connectClientSocket());
|
||||
}
|
||||
public TCPConnection(Tunnel t, Socket soc) throws IOException {
|
||||
public TCPConnection( Socket soc) throws IOException {
|
||||
connect = soc;
|
||||
tunnel = t;
|
||||
if(t!=null) {
|
||||
t.getCCount().incrementAndGet();
|
||||
initIO();
|
||||
}
|
||||
din = new DataInputStream(connect.getInputStream());
|
||||
|
||||
|
||||
|
||||
protected void initIO() throws IOException {
|
||||
dout = new DataOutputStream( connect.getOutputStream());
|
||||
din = new DataInputStream(connect.getInputStream());
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
@@ -109,22 +72,4 @@ public class TCPConnection {
|
||||
}
|
||||
|
||||
|
||||
private volatile long time=System.nanoTime();
|
||||
public boolean checkPingTime() {
|
||||
long cu=System.nanoTime();
|
||||
if(cu-time>Consts.PINGTIMENS) {
|
||||
time=cu;
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private volatile long RTT=10000000;
|
||||
public void nextRTT(long NRTT) {
|
||||
RTT=(long) ((1.0-Consts.A)*RTT+Consts.A*NRTT);
|
||||
System.out.println(RTT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class Tunnel {
|
||||
}
|
||||
public Socket connectClientSocket() throws UnknownHostException, IOException {
|
||||
Socket socket=new Socket();
|
||||
socket.connect(ipport.getSocketAddress(), 5000);
|
||||
socket.connect(ipport.getSocketAddress(), 10000);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@@ -109,5 +109,4 @@ public class Tunnel {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,478 @@
|
||||
package org.kne.ui;
|
||||
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Point;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SpringLayout;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import java.awt.Font;
|
||||
import java.awt.Image;
|
||||
|
||||
import javax.swing.SwingConstants;
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
public class XFrame extends JFrame {
|
||||
MouseListener lsr=new MouseListener() {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if(e.getButton()==MouseEvent.BUTTON1) {
|
||||
delta.x = e.getXOnScreen()-XFrame.this.getX();
|
||||
delta.y = e.getYOnScreen()-XFrame.this.getY();
|
||||
delta0.x = e.getXOnScreen()-(XFrame.this.getX()+XFrame.this.getWidth());
|
||||
delta0.y = e.getYOnScreen()-(XFrame.this.getY()+XFrame.this.getHeight());
|
||||
total.x=XFrame.this.getWidth()+XFrame.this.getX();
|
||||
total.y=XFrame.this.getHeight()+XFrame.this.getY();
|
||||
xb=e.getY()<=8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Container getContentPane() {
|
||||
return content;
|
||||
}
|
||||
|
||||
private static final Color invisible=new Color(255,255,255, 1);
|
||||
private JPanel titlepanel;
|
||||
private Point delta = new Point();
|
||||
private Point delta0 = new Point();
|
||||
private Point total = new Point();
|
||||
private boolean xb;
|
||||
private int state=0;
|
||||
|
||||
private JPanel content;
|
||||
private JLabel titlelabel;
|
||||
private JLabel iconi;
|
||||
|
||||
@Override
|
||||
public void setIconImage(Image image) {
|
||||
iconi.setIcon(new ImageIcon(image.getScaledInstance(27,27, Image.SCALE_SMOOTH)));
|
||||
super.setIconImage(image);
|
||||
repaint();
|
||||
}
|
||||
public void setTitleColor(Color c) {
|
||||
titlepanel.setBackground(c);
|
||||
repaint();
|
||||
}
|
||||
public Color getTitleColor() {
|
||||
return titlepanel.getBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(String title) {
|
||||
titlelabel.setText(title);
|
||||
super.setTitle(title);
|
||||
repaint();
|
||||
}
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return super.getTitle();
|
||||
}
|
||||
|
||||
public XFrame() {
|
||||
setUndecorated(true);
|
||||
|
||||
super.setBackground(new Color(255, 255, 255, 0));
|
||||
Container contentPane = super.getContentPane();
|
||||
contentPane.setBackground(new Color(255, 255, 255, 0));
|
||||
SpringLayout springLayout = new SpringLayout();
|
||||
contentPane.setLayout(springLayout);
|
||||
|
||||
titlepanel = new JPanel();
|
||||
//titlepanel.setOpaque(false);
|
||||
titlepanel.setBorder(null);
|
||||
springLayout.putConstraint(SpringLayout.WEST, titlepanel, 8, SpringLayout.WEST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, titlepanel, 31, SpringLayout.NORTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.EAST, titlepanel, -8, SpringLayout.EAST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.NORTH, titlepanel, 0, SpringLayout.NORTH, contentPane);
|
||||
contentPane.add(titlepanel);
|
||||
titlepanel.addMouseListener(lsr);
|
||||
titlepanel.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if(e.getY()<=8) {
|
||||
titlepanel.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
|
||||
}else {
|
||||
titlepanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
if(xb) {
|
||||
XFrame.this.setLocation(XFrame.this.getX(),p.y-delta.y);
|
||||
XFrame.this.setSize(XFrame.this.getWidth(), total.y-(p.y-delta.y));
|
||||
}else {
|
||||
XFrame.this.setLocation(p.x-delta.x,p.y-delta.y);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JPanel lu = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, lu, 0, SpringLayout.NORTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.WEST, lu, 0, SpringLayout.WEST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, lu, 8, SpringLayout.NORTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.EAST, lu, 8, SpringLayout.WEST, contentPane);
|
||||
lu.setBackground(invisible);
|
||||
lu.addMouseListener(lsr);
|
||||
lu.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
|
||||
lu.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setLocation(p.x-delta.x,p.y-delta.y);
|
||||
XFrame.this.setSize( total.x-(p.x-delta.x),total.y-(p.y-delta.y));
|
||||
|
||||
}
|
||||
});
|
||||
contentPane.add(lu);
|
||||
|
||||
JPanel ru = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, ru, 0, SpringLayout.NORTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.WEST, ru, -8, SpringLayout.EAST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, ru, 8, SpringLayout.NORTH,contentPane);
|
||||
springLayout.putConstraint(SpringLayout.EAST, ru, 0, SpringLayout.EAST, contentPane);
|
||||
ru.setBackground(invisible);
|
||||
ru.addMouseListener(lsr);
|
||||
ru.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
|
||||
ru.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setLocation(XFrame.this.getX(),p.y-delta.y);
|
||||
XFrame.this.setSize(p.x+delta0.x-XFrame.this.getX(), total.y-(p.y-delta.y));
|
||||
|
||||
}
|
||||
});
|
||||
contentPane.add(ru);
|
||||
|
||||
JPanel ld = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, ld, -8, SpringLayout.SOUTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.WEST, ld, 0, SpringLayout.WEST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, ld, 0, SpringLayout.SOUTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.EAST, ld, 8, SpringLayout.WEST, contentPane);
|
||||
ld.setBackground(invisible);
|
||||
ld.addMouseListener(lsr);
|
||||
ld.setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
|
||||
ld.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setLocation(p.x-delta.x,XFrame.this.getY());
|
||||
XFrame.this.setSize( total.x-(p.x-delta.x),p.y+delta0.y-XFrame.this.getY());
|
||||
}
|
||||
});
|
||||
contentPane.add(ld);
|
||||
|
||||
JPanel rd = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, rd, -8, SpringLayout.SOUTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.WEST, rd, -8, SpringLayout.EAST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, rd, 0, SpringLayout.SOUTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.EAST, rd, 0, SpringLayout.EAST, contentPane);
|
||||
rd.setBackground(invisible);
|
||||
rd.addMouseListener(lsr);
|
||||
rd.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
|
||||
rd.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setSize(p.x+delta0.x-XFrame.this.getX(), p.y+delta0.y-XFrame.this.getY());
|
||||
|
||||
}
|
||||
});
|
||||
contentPane.add(rd);
|
||||
|
||||
JPanel l = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, l, 0, SpringLayout.SOUTH, lu);
|
||||
springLayout.putConstraint(SpringLayout.WEST, l, 0, SpringLayout.WEST, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, l, 0, SpringLayout.NORTH, ld);
|
||||
springLayout.putConstraint(SpringLayout.EAST, l, 8, SpringLayout.WEST, contentPane);
|
||||
l.setBackground(invisible);
|
||||
l.addMouseListener(lsr);
|
||||
l.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
|
||||
l.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setLocation(p.x-delta.x,XFrame.this.getY());
|
||||
XFrame.this.setSize( total.x-(p.x-delta.x),XFrame.this.getHeight());
|
||||
|
||||
}
|
||||
});
|
||||
contentPane.add(l);
|
||||
|
||||
JPanel r = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, r, 0, SpringLayout.SOUTH, ru);
|
||||
springLayout.putConstraint(SpringLayout.WEST, r, -8, SpringLayout.EAST,contentPane);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, r, 0, SpringLayout.NORTH, rd);
|
||||
springLayout.putConstraint(SpringLayout.EAST, r, 0, SpringLayout.EAST, contentPane);
|
||||
r.setBackground(invisible);
|
||||
r.addMouseListener(lsr);
|
||||
r.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
||||
r.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setSize(p.x+delta0.x-XFrame.this.getX(), XFrame.this.getHeight());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
contentPane.add(r);
|
||||
|
||||
JPanel d = new JPanel();
|
||||
springLayout.putConstraint(SpringLayout.NORTH, d, -8, SpringLayout.SOUTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.WEST, d, 0, SpringLayout.EAST, ld);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, d, 0, SpringLayout.SOUTH, contentPane);
|
||||
springLayout.putConstraint(SpringLayout.EAST, d, 0, SpringLayout.WEST, rd);
|
||||
d.setBackground(invisible);
|
||||
d.addMouseListener(lsr);
|
||||
d.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
|
||||
d.addMouseMotionListener(new MouseMotionListener() {
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point p=e.getLocationOnScreen();
|
||||
XFrame.this.setSize(XFrame.this.getWidth(), p.y+delta0.y-XFrame.this.getY());
|
||||
|
||||
}
|
||||
});
|
||||
contentPane.add(d);
|
||||
|
||||
content = new JPanel();
|
||||
content.setBorder(null);
|
||||
springLayout.putConstraint(SpringLayout.NORTH, content, 0, SpringLayout.SOUTH, titlepanel);
|
||||
SpringLayout sl_titlepanel = new SpringLayout();
|
||||
titlepanel.setLayout(sl_titlepanel);
|
||||
|
||||
JButton close = new JButton("");
|
||||
close.setBackground(Color.WHITE);
|
||||
close.setForeground(Color.WHITE);
|
||||
close.setIcon(new ImageIcon(XFrame.class.getResource("/assets/close.png")));
|
||||
sl_titlepanel.putConstraint(SpringLayout.NORTH, close, 0, SpringLayout.NORTH, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.WEST, close, -46, SpringLayout.EAST, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.SOUTH, close, 0, SpringLayout.SOUTH, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.EAST, close, 0, SpringLayout.EAST, titlepanel);
|
||||
close.setBorderPainted(false);
|
||||
close.setContentAreaFilled(false);
|
||||
close.setFocusPainted(false);
|
||||
close.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
XFrame.super.processWindowEvent(new WindowEvent(XFrame.this, WindowEvent.WINDOW_CLOSING));
|
||||
|
||||
}
|
||||
});
|
||||
titlepanel.add(close);
|
||||
iconi = new JLabel("");
|
||||
iconi.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
sl_titlepanel.putConstraint(SpringLayout.NORTH, iconi, 0, SpringLayout.NORTH, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.WEST, iconi, 0, SpringLayout.WEST, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.SOUTH, iconi, 0, SpringLayout.SOUTH, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.EAST, iconi, 31, SpringLayout.WEST, titlepanel);
|
||||
iconi.setOpaque(false);
|
||||
iconi.setBackground(invisible);
|
||||
titlepanel.add(iconi);
|
||||
JButton maxium = new JButton("");
|
||||
maxium.setForeground(Color.WHITE);
|
||||
maxium.setBackground(Color.WHITE);
|
||||
maxium.setIcon(new ImageIcon(XFrame.class.getResource("/assets/maxium.png")));
|
||||
sl_titlepanel.putConstraint(SpringLayout.NORTH, maxium, 0, SpringLayout.NORTH, close);
|
||||
sl_titlepanel.putConstraint(SpringLayout.WEST, maxium, -46, SpringLayout.WEST, close);
|
||||
sl_titlepanel.putConstraint(SpringLayout.SOUTH, maxium, 0, SpringLayout.SOUTH, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.EAST, maxium, 0, SpringLayout.WEST, close);
|
||||
maxium.setBorderPainted(false);
|
||||
maxium.setContentAreaFilled(false);
|
||||
maxium.setFocusPainted(false);
|
||||
maxium.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int s=XFrame.this.getExtendedState();
|
||||
if(s==JFrame.NORMAL)
|
||||
XFrame.this.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
if(s==JFrame.MAXIMIZED_BOTH)
|
||||
XFrame.this.setExtendedState(JFrame.NORMAL);
|
||||
}
|
||||
});
|
||||
titlepanel.add(maxium);
|
||||
|
||||
JButton minium = new JButton("");
|
||||
minium.setForeground(Color.WHITE);
|
||||
minium.setBackground(Color.WHITE);
|
||||
minium.setIcon(new ImageIcon(XFrame.class.getResource("/assets/minium.png")));
|
||||
sl_titlepanel.putConstraint(SpringLayout.NORTH, minium, 0, SpringLayout.NORTH, close);
|
||||
sl_titlepanel.putConstraint(SpringLayout.WEST, minium, -46, SpringLayout.WEST, maxium);
|
||||
sl_titlepanel.putConstraint(SpringLayout.SOUTH, minium, 0, SpringLayout.SOUTH, close);
|
||||
sl_titlepanel.putConstraint(SpringLayout.EAST, minium, 0, SpringLayout.WEST, maxium);
|
||||
minium.setContentAreaFilled(false);
|
||||
minium.setBorderPainted(false);
|
||||
minium.setFocusPainted(false);
|
||||
//minium.setRolloverEnabled(false);
|
||||
minium.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int s=XFrame.this.getExtendedState();
|
||||
if(s!=JFrame.ICONIFIED) {
|
||||
state=s;
|
||||
XFrame.this.setExtendedState(JFrame.ICONIFIED);
|
||||
} else {
|
||||
XFrame.this.setExtendedState(state);
|
||||
}
|
||||
}
|
||||
});
|
||||
titlepanel.add(minium);
|
||||
|
||||
titlelabel = new JLabel();
|
||||
sl_titlepanel.putConstraint(SpringLayout.WEST, titlelabel, 31, SpringLayout.WEST, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.EAST, titlelabel, -31, SpringLayout.EAST, titlepanel);
|
||||
titlelabel.setFont(new Font("宋体", Font.PLAIN, 16));
|
||||
sl_titlepanel.putConstraint(SpringLayout.NORTH, titlelabel, 0, SpringLayout.NORTH, titlepanel);
|
||||
sl_titlepanel.putConstraint(SpringLayout.SOUTH, titlelabel, 0, SpringLayout.SOUTH, titlepanel);
|
||||
titlelabel.setOpaque(false);
|
||||
titlelabel.setBackground(invisible);
|
||||
titlepanel.add(titlelabel);
|
||||
springLayout.putConstraint(SpringLayout.WEST, content, 0, SpringLayout.EAST, l);
|
||||
springLayout.putConstraint(SpringLayout.SOUTH, content, 0, SpringLayout.NORTH, d);
|
||||
springLayout.putConstraint(SpringLayout.EAST, content, 0, SpringLayout.WEST, r);
|
||||
contentPane.add(content);
|
||||
content.setLayout(new BorderLayout(0, 0));
|
||||
addWindowListener(new WindowListener() {
|
||||
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
XFrame.this.setExtendedState(state);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user