Server
serverSocketChannel用于ServerSocketChannel的建立和端口的绑定。
byteBuffer用于不同Channel之间的数据交互。
selector用于监听服务器各个Channel上数据的变化并做出响应。
构造函数调用了初始化ServerSocketChannel的操作,定义了listener方法监听Channel数据变化,解析客户端的数据并对客户端的请求做出响应。
public class MyServer {
private int size = 1024;
private ServerSocketChannel serverSocketChannel;
private ByteBuffer byteBuffer;
private Selector selector;
private int remoteClientNum = 0;
public MyServer(int port) {
try {
initChannel(port);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
//Channel初始化
public void initChannel (int port) throws IOException {
serverSocketChannel = ServerSocketChannel.open();//打开
serverSocketChannel.configureBlocking(false);//设置为非阻塞模式
serverSocketChannel.bind(new InetSocketAddress(port));//绑定端口
System.out.println("listener on port: " + port);
selector = Selector.open();//选择注册通道
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
byteBuffer = ByteBuffer.allocate(size);//缓冲区大小
}
//监听器
private void listener() throws Exception {
while (true) {
int n = selector.select();
if (n == 0) {
continue;
}
Iterator<SelectionKey> interator =
selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
registerChannel (selector, channel, SelectionKey.OP_READ);
remoteClientNum++;
System.out.println("Online client num="+remoteClientNum);
write(channel,"hello client".getBytes());
}
if(key.isReadable()) {
read(key);
}
iterator.remove();
}
}
}
private void read(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
int count;
byteBuffer.clear();
while ((count = socketChannel.read(byteBuffer)) > 0) {
byteBuffer.flip();
while (byteBuffer.hasRemaining()) {
System.out.println((char)byteBuffer.get());
}
byteBuffer.clear;
}
if(count < 0) {
socketChannel.close();
}
}
private void write(SocketChannel channel,byte[] writeData) throws IOException {
byteBuffer.clear();
byteBuffer.put(writeData);
byteBuffer.flip();
channel.write(byteBuffer);
}
private void registerChannel(Selector selector, SocketChannel channel, int opRead) throws IOException {
if(channel == null) {
return;
}
channel.configureBlocking(false);
channel.register(selector, opRead);
}
public static void main(String[] args) {
try{
MyServer myServer = new MyServer(9999);
myServer.listener();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client
connectServer用于和服务器建立连接,receive方法用于接收服务端发来的数据,send2Server用于向服务端发送数据。
public class MyClient {
private int size = 1024;
private ByteBuffer byteBuffer;
private SocketChannel socketChannel;
public void connectServer() throws IOException {
socketChannel = socketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
socketChannel.configureBlocking(false);
byteBuffer = ByteBuffer.allocate(size);
receive();
}
private void receive() throws IOException {
while (true) {
byteBuffer.clear();
int count;
while ((count = socketChannel.read(byteBuffer)) > 0) {
byteBuffer.flip();
while (byteBuffer.hasRemaining()) {
System.out.print((char)byteBuffer.get());
}
send2Server("say hi".getBytes());
byteBuffer.clear();
}
}
}
private void send2Server(byte[] bytes) throws IOException {
byteBuffer.clear();
byteBuffer.put(bytes);
byteBuffer.flip();
socketChannel.write(byteBuffer);
}
public static void main(String[] args) throws IOException {
new MyClient().connectServer();
}
}