NIO 實例demo-Client
Client部分包括Client和ClientHandle兩部分其中Client的時序通信圖如下
Client.java
Client端啓動主函數如下
package MyTestNetty.Server;
/**
* Created by User on 2017/8/4.
*/
public class Client {
public static void main(String[] args) {
int port = 8080;//指定端口號
new Thread(new TimeClientHandle1("127.0.0.1",port),"myclient").start();//啓動監聽線程
}
}
TimeClientHandle1.java
第二部分是ClientHandler部分代碼如下:
package MyTestNetty.Server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
* Created by User on 2017/8/4.
*/
public class TimeClientHandle1 implements Runnable {
private String host;
private int port;
private Selector selector;
private SocketChannel socketChannel;
private volatile boolean stop;
public TimeClientHandle1(String host, int port) {
this.host = host == null ? "127.0.0.1" : host;
this.port = port;
try {
selector = Selector.open();//創建selector實例
socketChannel = SocketChannel.open();//創建socketChannel實例
socketChannel.configureBlocking(false);//設置爲異步
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
@Override
public void run() {
try{
doConnect();
}catch (IOException e){
e.printStackTrace();
System.exit(1);
}
while (!stop){//輪詢查詢可用的key
try{
selector.select(1000);
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectionKeys.iterator();
SelectionKey key = null;
while (it.hasNext()){
key = it.next();
it.remove();
try {
hadleInput(key);
}
catch (Exception e){
if(key!=null){
key.cancel();
if(key.channel()!=null)
key.channel().close();
}
}
}
}catch (Exception e){
e.printStackTrace();
System.exit(1);
}
}
// 多路複用器關閉後,所有註冊在上面的Channel和Pipe等資源都會被自動註冊並關閉,所以不需要重新釋放資源
if(selector!=null){
try {
selector.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
private void hadleInput(SelectionKey key) throws IOException {
if(key.isValid()){
SocketChannel sc = (SocketChannel)key.channel();
if(key.isConnectable()){
if(sc.finishConnect()){
sc.register(selector,SelectionKey.OP_READ);
doWrite(sc);//向服務啓發送請求(先寫緩衝)
}else{
System.exit(1);
}
}
if(key.isReadable()){//讀取服務端返回的數據,從還緩衝中讀數據
// read data
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int readBytes = sc.read(readBuffer);
if(readBytes>0){
readBuffer.flip();
byte[] bytes=new byte[readBuffer.remaining()];
readBuffer.get(bytes);
String body = new String(bytes,"UTF-8");
System.out.println("Hello glad to see you : " + body);
this.stop=true;
}
else if(readBytes<0){
// 對端鏈路關閉
key.cancel();
sc.close();
}
else ; // 讀到0字節,忽略
}
}
}
private void doConnect() throws IOException {
if(socketChannel.connect(new InetSocketAddress(host,port))){
socketChannel.register(selector,SelectionKey.OP_READ);
doWrite(socketChannel);
}else{
socketChannel.register(selector,SelectionKey.OP_CONNECT);
}
}
private void doWrite(SocketChannel sc) throws IOException {
byte[] req = "Clients ".getBytes();
ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
writeBuffer.put(req);
writeBuffer.flip();
sc.write(writeBuffer);
if(!writeBuffer.hasRemaining()){
System.out.println("send order to server succeed!");
}
}
}
這一部分主要是包括向服務器發送請求,以及接受來自server的信息,啓動運行後可輸出一下結果表示服務端啓動成功(本例中我們向服務器發送的是Clients 字符串)服務器給我們反饋的是Server)
並且在服務端的控制檯輸出如下:
這個簡單的服務器客戶端NIO通信的簡單demo