package example;
/**
* 端口转发
*/
//import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
public class myServer {
public static final int PORTClient = 8085;
public static final int PORTDevice = 8081;
protected static HashMap map = new HashMap();
//定义选择器
protected Selector selector;
protected Selector selector_device;
int clientCount;
int deviceCount;
public myServer() throws Exception {
//外部访问的socket和selector
selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(PORTClient)); // port
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// register
p("Server localhost:" + PORTClient + " started. waiting for clients. ");
//内部设备端口
selector_device=Selector.open();
ServerSocketChannel serverSocketChannelDevice = ServerSocketChannel.open();
serverSocketChannelDevice.socket().bind(new InetSocketAddress(PORTDevice));
serverSocketChannelDevice.configureBlocking(false);
serverSocketChannelDevice.register(selector_device, SelectionKey.OP_ACCEPT);
p("Server localhost:" + PORTDevice + " started. waiting for Device. ");
Client client=new Client();
Device device=new Device();
device.run();
while (true) {
client.run();
}
}
class Client implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
try {
// selector 线程。select() 会阻塞,直到有客户端连接,或者有消息读入
selector.select();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Iterator iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
// hashmap.put(, selectionKey);
iterator.remove(); // 删除此消息
// 并在当前线程内处理。(为了高效,一般会在另一个线程中处理此消息,例如使用线程池等)
try {
handleSelectionKey(selectionKey);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void start() {
// TODO Auto-generated method stub
}
}
class Device implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
//
try {
selector_device.select();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Iterator iteratorDevice = selector_device.selectedKeys().iterator();
while (iteratorDevice.hasNext()) {
SelectionKey selectionKeyDevice = iteratorDevice.next();
System.out.println(selectionKeyDevice);
// hashmap.put(, selectionKey);
iteratorDevice.remove(); // 删除此消息
// 并在当前线程内处理。(为了高效,一般会在另一个线程中处理此消息,例如使用线程池等)
try {
handleDevice(selectionKeyDevice);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void start() {
// TODO Auto-generated method stub
}
}
//内部设备连接
private void handleDevice(SelectionKey selectionKeyDevice) throws IOException {
// TODO Auto-generated method stub
if (selectionKeyDevice.isAcceptable()) {
// 有客户端进来
deviceCount++;
System.out.println(deviceCount);
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKeyDevice.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
Socket socket = socketChannel.socket();
// 立即注册一个 OP_READ 的SelectionKey, 接收客户端的消息
SelectionKey key = socketChannel.register(selector_device, SelectionKey.OP_READ);
System.out.println(key);
String str=socket.getRemoteSocketAddress().toString();
String [] strs = str.split("[:]");
//做内部设备的访问map
map.put(strs[0], key);
System.out.println(map.get(socket.getRemoteSocketAddress()));
System.out.println(socket.getInetAddress().getHostAddress());
key.attach("第 " + deviceCount + " 个内部设备 [" + socket.getRemoteSocketAddress() + "]: ");
p(key.p_w_upload() + "\t[connected] =========================================");
} else if (selectionKeyDevice.isReadable()) {
// 有消息进来
ByteBuffer byteBufferD = ByteBuffer.allocate(100);
SocketChannel socketChannel = (SocketChannel) selectionKeyDevice.channel();
try {
int len = socketChannel.read(byteBufferD);
if (len > 0) {
byteBufferD.flip();//flip()方法用来将缓冲区准备为数据传出状态,这通过将limit设置为position的当前值,再 将position的值设为0来实现
socketChannel.write(byteBufferD);
//socketChannelDevice.write(byteBuffer);
} else {
// 输入结束,关闭 socketChannel
p(selectionKeyDevice.p_w_upload() + "read finished. close socketChannel. ");
socketChannel.close();
}
} catch (Exception e) {
// 如果read抛出异常,表示连接异常中断,需要关闭 socketChannel
e.printStackTrace();
p(selectionKeyDevice.p_w_upload() + "socket closed? ");
socketChannel.close();
}
} else if (selectionKeyDevice.isWritable()) {
p(selectionKeyDevice.p_w_upload() + "TODO: isWritable() ???????????????????????????? ");
} else if (selectionKeyDevice.isConnectable()) {
p(selectionKeyDevice.p_w_upload() + "TODO: isConnectable() ????????????????????????? ");
} else {
p(selectionKeyDevice.p_w_upload() + "TODO: else. ");
}
}
//外部用户访问
public void handleSelectionKey(SelectionKey selectionKey) throws Exception {
if (selectionKey.isAcceptable()) {
// 有客户端进来
clientCount++;
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
Socket socket = socketChannel.socket();
System.out.println(serverSocketChannel.socket().getLocalSocketAddress());
// 立即注册一个 OP_READ 的SelectionKey, 接收客户端的消息
SelectionKey key = socketChannel.register(selector, SelectionKey.OP_READ);
key.attach("第 " + clientCount + " 个客户端 [" + socket.getRemoteSocketAddress() + "]: ");
p(key.p_w_upload() + "\t[connected] =========================================");
} else if (selectionKey.isReadable()) {
// 有消息进来
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
ByteBuffer byteBufferDD= ByteBuffer.allocate(100);
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
SocketChannel socketChannelDevice=(SocketChannel)map.get("/192.168.1.102").channel();
System.out.println(map.get("/192.168.1.102"));
//System.out.println(socketChannelDevice.socket().getPort());
try {
//向设备发指令
int instruction = socketChannel.read(byteBuffer);
int data=socketChannelDevice.read(byteBufferDD);
if (instruction > 0) {
byteBuffer.flip();//flip()方法用来将缓冲区准备为数据传出状态,这通过将limit设置为position的当前值,再 将position的值设为0来实现
//socketChannel.write(byteBuffer);
socketChannelDevice.write(byteBuffer);
}
//向外部连接传数据
else if (data > 0)
{
byteBuffer.flip();
socketChannel.write(byteBuffer);
} else {
// 输入结束,关闭 socketChannel
p(selectionKey.p_w_upload() + "read finished. close socketChannel. ");
socketChannel.close();
}
} catch (Exception e) {
// 如果read抛出异常,表示连接异常中断,需要关闭 socketChannel
e.printStackTrace();
p(selectionKey.p_w_upload() + "socket closed? ");
socketChannel.close();
}
} else if (selectionKey.isWritable()) {
p(selectionKey.p_w_upload() + "TODO: isWritable() ???????????????????????????? ");
} else if (selectionKey.isConnectable()) {
p(selectionKey.p_w_upload() + "TODO: isConnectable() ????????????????????????? ");
} else {
p(selectionKey.p_w_upload() + "TODO: else. ");
}
}
public static void p(Object object) {
System.out.println(object);
}
public static void main(String[] args) throws Exception {
new myServer();
}
}