227 lines
6.0 KiB
Java
227 lines
6.0 KiB
Java
package org.kne.cloud.network.klalb;
|
|
|
|
import java.io.IOException;
|
|
import java.io.StreamCorruptedException;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.SocketException;
|
|
import java.net.StandardSocketOptions;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.Channels;
|
|
import java.nio.channels.GatheringByteChannel;
|
|
import java.nio.channels.ScatteringByteChannel;
|
|
import java.nio.channels.SocketChannel;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
import org.kne.cloud.network.BufferedChannel;
|
|
import org.kne.cloud.network.MultipurposeSocketAddress;
|
|
import org.kne.cloud.network.NetworkPacket;
|
|
import org.kne.cloud.network.ThreadTool;
|
|
import org.kne.io.KNEChannels;
|
|
|
|
public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
|
|
private static final boolean debug = false;
|
|
private volatile long timeoutTimer;
|
|
private volatile boolean timerenabled=false;
|
|
private boolean enableBuffer=true;
|
|
private Runnable timeouter=new Runnable() {
|
|
public void run() {
|
|
timeoutTimer=System.nanoTime();
|
|
while(connectSocket.isOpen()) {
|
|
if(timerenabled&&(System.nanoTime()-timeoutTimer>sotimeout*1000000L)) {
|
|
if(connectSocket!=null)
|
|
try {
|
|
connectSocket.close();
|
|
} catch (IOException e) {
|
|
}
|
|
}
|
|
try {
|
|
Thread.sleep(5);
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
@Override
|
|
public String toString() {
|
|
try {
|
|
return new MultipurposeSocketAddress("TCP",(InetSocketAddress)connectSocket.getLocalAddress())+"←"+new MultipurposeSocketAddress("TCP",(InetSocketAddress)connectSocket.getRemoteAddress());
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return "?←?";
|
|
}
|
|
}
|
|
|
|
private SocketChannel connectSocket;
|
|
private ScatteringByteChannel readableChannel;
|
|
private GatheringByteChannel writableChannel;
|
|
private int sotimeout=getDefaultSoTimeout();
|
|
public StreamChannelKLALBPacketLink(SocketChannel connectSocket) throws IOException {
|
|
this(connectSocket,true);
|
|
}
|
|
public StreamChannelKLALBPacketLink(SocketChannel connectSocket,boolean enableBuffer) throws IOException {
|
|
try {
|
|
this.connectSocket=connectSocket;
|
|
if(enableBuffer) {
|
|
BufferedChannel buf=new BufferedChannel(connectSocket,connectSocket,256*1024);
|
|
this.readableChannel =buf;
|
|
this.writableChannel =buf;
|
|
}else {
|
|
this.readableChannel=connectSocket;
|
|
this.writableChannel=connectSocket;
|
|
}
|
|
this.enableBuffer=enableBuffer;
|
|
connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true);
|
|
ThreadTool.makeVDaemonThread("连接超时计时线程", timeouter);
|
|
new KLALBOutputStream(Channels.newOutputStream(writableChannel));
|
|
if(writableChannel instanceof BufferedChannel)
|
|
((BufferedChannel) writableChannel).flush();
|
|
new KLALBInputStream(Channels.newInputStream(readableChannel));
|
|
}catch(Throwable e) {
|
|
connectSocket.close();
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
//System.out.println("连接被关闭");
|
|
//new Exception().printStackTrace();
|
|
connectSocket.close();
|
|
}
|
|
|
|
@Override
|
|
public boolean isClosed() {
|
|
return !connectSocket.isOpen();
|
|
}
|
|
|
|
@Override
|
|
public void setSoTimeout(int val) throws SocketException {
|
|
sotimeout=val;
|
|
}
|
|
|
|
@Override
|
|
public int getSoTimeout() throws SocketException {
|
|
return sotimeout;
|
|
}
|
|
|
|
@Override
|
|
public void flush() throws IOException {
|
|
checkflush();
|
|
}
|
|
|
|
@Override
|
|
public boolean isStream() {
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
public void writePacket(ByteBuffer kp) throws IOException {
|
|
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
|
|
szeWrite.limit(4);
|
|
//szeWrite.clear();
|
|
szeWrite.putInt(kp.limit());
|
|
szeWrite.flip();
|
|
KLALBVirtualSocketChannel obj = null;
|
|
writableChannel.write(new ByteBuffer[] {szeWrite,kp});
|
|
checkflush();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
public ByteBuffer readPacket() throws IOException {
|
|
|
|
ByteBuffer szeRead=NetworkPacket.bufferAllocator.allocate(4);
|
|
timeoutTimer=System.nanoTime();
|
|
timerenabled=true;
|
|
ByteBuffer kp;
|
|
szeRead.clear();
|
|
szeRead.limit(4);
|
|
//szeRead.clear();
|
|
try {
|
|
KNEChannels.readFully(readableChannel,szeRead);
|
|
szeRead.flip();
|
|
int size=szeRead.getInt(0);
|
|
kp=NetworkPacket.bufferAllocator.allocate(size);
|
|
kp.limit(size);
|
|
KNEChannels.readFully(readableChannel, kp);
|
|
kp.flip();
|
|
return kp;
|
|
}finally {
|
|
timerenabled=false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
|
|
|
|
/*ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
|
|
szeWrite.limit(4);
|
|
//szeWrite.clear();
|
|
int length=(int) kp.getTotalLength();
|
|
szeWrite.putInt(0,length);
|
|
szeWrite.flip();
|
|
|
|
|
|
|
|
writableChannel.write(szeWrite);*/
|
|
|
|
if(debug) {
|
|
|
|
int length=(int) kp.getTotalLength();
|
|
AtomicLong al=new AtomicLong(0);
|
|
KLALBPacket.writeKLALBPacketToChannel(new MonitoredChannel(writableChannel,null,new AtomicLong[] { al}), kp);
|
|
if(length!=al.get()) {
|
|
throw new StreamCorruptedException(kp+" packet length error:"+al.get()+"!="+length);
|
|
}
|
|
}else {
|
|
KLALBPacket.writeKLALBPacketToChannel(writableChannel, kp);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private void checkflush() throws IOException {
|
|
if(writableChannel instanceof BufferedChannel) {
|
|
((BufferedChannel) writableChannel).flush();
|
|
}else if(writableChannel instanceof KLALBVirtualSocketChannel) {
|
|
((KLALBVirtualSocketChannel) writableChannel).flush();
|
|
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public KLALBPacket readKLALBPacket() throws IOException {
|
|
|
|
/*ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
|
|
szeWrite.limit(4);
|
|
KNEChannels.readFully(readableChannel, szeWrite);
|
|
szeWrite.flip();
|
|
int readSize=szeWrite.getInt();*/
|
|
KLALBPacket kp=KLALBPacket.readKLALBPacketFromChannel(readableChannel);
|
|
if(debug) {
|
|
int readSize=0;
|
|
long kpl=kp.getTotalLength();
|
|
if(kpl!=readSize) {
|
|
throw new StreamCorruptedException(kp+" packet length error:"+kpl+"!="+readSize);
|
|
}
|
|
}
|
|
return kp;
|
|
}
|
|
|
|
|
|
|
|
}
|