今天練習了一下以前學過的NIO編程,寫了一個NIO 通信的小示例,希望以後看到這個案例時,可以理解NIO通信的原理
示例代碼如下
服務器端
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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
* 進行使用Nio套接字來開發我們的tomcat的的服務器的連接操作
* @author Administrator
* 通過調用open方法得到一個ServerSocketChannel通道
* 但是這個通道還沒有被綁定地址通過調用調用bind()方法來進行綁定數據
*
*/
public class SocketServer {
public static void start(){
try {
//先進行創建一個轉詢容器
Selector sel=Selector.open();
//通過open的方法得到nio的套接字通道
ServerSocketChannel server=ServerSocketChannel.open();
//進行綁定我們的地址
server.bind(new InetSocketAddress("localhost",8080),2500);
//進行設置非阻塞的操作的方法
server.configureBlocking(false);
//先進行把我們SSC註冊入SelectKey容器當中,同時這個註冊服務器通道的感興趣事件(這個事件有4種)
server.register(sel, SelectionKey.OP_ACCEPT);
while(true){
//進行輪詢的桃選已發生的操作感興趣事件,放入一個selected key集合當中
sel.select(); //是一個阻塞的操作的方法,是一個集合
//進行得到精選key的集合
Set<SelectionKey> set=sel.selectedKeys();
//進行遍歷所以的發生的key
Iterator<SelectionKey> it=set.iterator();
while(it.hasNext()){
//得到桃選的key
SelectionKey key=it.next();
//判斷這個key是否爲服務器的連接方法,如果是則進行連接,得到客戶端的通道
if(key.isAcceptable()){
ServerSocketChannel sch=(ServerSocketChannel)key.channel();
//進行接收請求然後進行註冊
SocketChannel ch=sch.accept();
//這個也要進行配置我們非阻塞模式
ch.configureBlocking(false);
//然後進行客戶端的註冊的感興趣事件
ch.register(sel,SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}
//如果這個是一個讀請求,那麼則
if(key.isReadable()){
//進行得到客戶端的通道
SocketChannel sc=(SocketChannel) key.channel();
//進行讀取數據
String str=readFormClient(sc);
System.out.println("from client: "+str);
}
if(key.isWritable()){
ByteBuffer buffer=ByteBuffer.allocate(1024);
buffer.put("數據從服務器發送....".getBytes());
//進行寫數據
SocketChannel sc=(SocketChannel)key.channel();
buffer.flip();
sc.write(buffer);
buffer.clear();
}
if(key.isConnectable()){
System.out.println("client connectable");
}
}
//進行移除這個key數據
it.remove();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String readFormClient(SocketChannel sc){
ByteBuffer buffer=ByteBuffer.allocate(1024);
String str=null;
try {
int len=sc.read(buffer);
if(len==-1){
System.out.println("from client:數據已經讀取完成...");
}else if(len>0) {
//進行壓縮
buffer.flip();
str=new String(buffer.array(),0,buffer.limit());
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
return str.trim();
}
}
服務器的main方法如下:
/**
* 我們的NIO的啓動類
* @author Administrator
*
*/
public class Bootstrap {
public static void main(String[] args) {
//網絡Socket通信
SocketServer.start();
}
}
客戶端代碼如下:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
public class SocketChannelClient {
public static void main(String[] args) {
// 先註冊輪詢
try {
//Selector selector = Selector.open();
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 創建一個輸入流通道
ReadableByteChannel incha = Channels.newChannel(System.in);
// 進行向服務器連接
SocketChannel sc = null;
sc = SocketChannel.open(new InetSocketAddress("localhost", 8080));
sc.configureBlocking(false);
// 進行連接操作
// sc.connect(new InetSocketAddress("localhsot",8080));
while (!sc.finishConnect()) {
}
// 進行從客戶端輸入數據,然後輸出數據
while (true) {
incha.read(buffer);
buffer.flip();
sc.write(buffer);
buffer.clear();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
客戶端代碼二如下:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class SocketChannelClient2 {
public static void main(String[] args) {
try {
// 先註冊輪詢
Selector sel = Selector.open();
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 創建一個輸入流通道
ReadableByteChannel incha = Channels.newChannel(System.in);
// 進行向服務器連接
SocketChannel sc = null;
sc = SocketChannel.open(new InetSocketAddress("localhost", 8080));
sc.configureBlocking(false);
while (!sc.finishConnect()) {
}
// 進行連接操作
// sc.connect(new InetSocketAddress("localhsot",8080));
//進行註冊
sc.register(sel,SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);
// 進行從客戶端輸入數據,然後輸出數據
while (true) {
//進行挑選操作
sel.select();
Iterator<SelectionKey> it=sel.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey key=it.next();
if(key.isConnectable()){
//進行連接服務器
System.out.println("連接服務器...");
}
if(key.isWritable()){
//得到通道
sc=(SocketChannel) key.channel();
System.out.println("輸入你要發送的數據:");
incha.read(buffer);
buffer.flip();
sc.write(buffer);
buffer.clear();
}
if(key.isReadable()){
//進行讀取數據通道
sc=(SocketChannel) key.channel();
//buffer.clear();
int len=sc.read(buffer);
if(len==-1){
System.out.println("到文件未了...");
}else if(len>0){
buffer.flip();
String str=new String(buffer.array(),0,buffer.limit()).trim();
buffer.clear();
System.out.println("from server:"+str);
}
}
it.remove();
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}