第0章:簡介
第1章:阻塞通信實踐
(1)服務端(SocketServerTest.java)
package com.mcc.core.test.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* socket服務端
*
* @author <a href="mailto:[email protected]">menergy</a>
* DateTime: 14-2-15 上午12:08
*/
public class SocketServerTest {
public static void main(String arg[]){
try{
ServerSocket server=null;
try{
server=new ServerSocket(4700);//創建一個ServerSocket在端口4700監聽客戶請求
}catch(Exception e) {
System.out.println("can not listen to:"+e);//出錯,打印出錯信息
}
Socket socket=null;
try{
socket=server.accept();//使用accept()阻塞等待客戶請求,有客戶請求到來則產生一個Socket對象,並繼續執行
}catch(Exception e) {
System.out.println("Error."+e);//出錯,打印出錯信息
}
String line;
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket對象得到輸入流,並構造相應的BufferedReader對象
PrintWriter os=new PrintWriter(socket.getOutputStream());//由Socket對象得到輸出流,並構造PrintWriter對象
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));//由系統標準輸入設備構造BufferedReader對象
System.out.println("Client:"+is.readLine());
//在標準輸出上打印從客戶端讀入的字符串
line=sin.readLine();//從標準輸入讀入一字符串
while(!line.equals("bye")){//如果該字符串爲 "bye",則停止循環
os.println(line);//向客戶端輸出該字符串
os.flush();//刷新輸出流,使Client馬上收到該字符串
System.out.println("Server:"+line);//在系統標準輸出上打印讀入的字符串
System.out.println("Client:"+is.readLine());//從Client讀入一字符串,並打印到標準輸出上
line=sin.readLine();//從系統標準輸入讀入一字符串
}//繼續循環
os.close(); //關閉Socket輸出流
is.close(); //關閉Socket輸入流
socket.close(); //關閉Socket
server.close(); //關閉ServerSocket
}catch(Exception e){
System.out.println("Error:"+e);//出錯,打印出錯信息
}
}
}
(2)客戶端(SocketClientTest.java)
package com.mcc.core.test.socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* socket客戶端
*
* @author <a href="mailto:[email protected]">menergy</a>
* DateTime: 14-2-14 下午11:59
*/
public class SocketClientTest {
public static void main(String arg[]){
try{
Socket socket=new Socket("127.0.0.1",4700);//向本機的4700端口發出客戶請求
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));//由系統標準輸入設備構造BufferedReader對象
PrintWriter os=new PrintWriter(socket.getOutputStream());//由Socket對象得到輸出流,並構造PrintWriter對象
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket對象得到輸入流,並構造相應的BufferedReader對象
String readline;
readline=sin.readLine(); //從系統標準輸入讀入一字符串
while(!readline.equals("bye")){//若從標準輸入讀入的字符串爲 "bye"則停止循環
os.println(readline);//將從系統標準輸入讀入的字符串輸出到Server
os.flush();//刷新輸出流,使Server馬上收到該字符串
System.out.println("Client:"+readline);//在系統標準輸出上打印讀入的字符串
System.out.println("Server:"+is.readLine());//從Server讀入一字符串,並打印到標準輸出上
readline=sin.readLine(); //從系統標準輸入讀入一字符串
} //繼續循環
os.close(); //關閉Socket輸出流
is.close(); //關閉Socket輸入流
socket.close(); //關閉Socket
}catch(Exception e) {
System.out.println("Error"+e); //出錯,則打印出錯信息
}
}
}
第2章:非阻塞通信實踐
(1)服務端(NIOServer.java)
package com.mcc.core.socket.server;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
/**
* 無阻塞IO服務器
*
* @author <a href="mailto:[email protected]">menergy</a>
* DateTime: 14-2-24 上午10:39
*/
public class NIOServer {
static int BLOCK = 4096;
// 處理與客戶端的交互
public class HandleClient {
protected FileChannel channel;
protected ByteBuffer buffer;
public HandleClient() throws IOException {
this.channel = new FileInputStream(filename).getChannel();
this.buffer = ByteBuffer.allocate(BLOCK);
}
public ByteBuffer readBlock() {
try {
buffer.clear();
int count = channel.read(buffer);
buffer.flip();
if (count <= 0)
return null;
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
public void close() {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected Selector selector;
protected String filename = "e://data/ctbCgiInfo_2014.txt"; // a big file
protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);
protected CharsetDecoder decoder;
public NIOServer(int port) throws IOException {
selector = this.getSelector(port);
Charset charset = Charset.forName("UTF-8");
decoder = charset.newDecoder();
}
// 獲取Selector
protected Selector getSelector(int port) throws IOException {
ServerSocketChannel server = ServerSocketChannel.open();
Selector sel = Selector.open();
server.socket().bind(new InetSocketAddress(port));
server.configureBlocking(false);
server.register(sel, SelectionKey.OP_ACCEPT);
return sel;
}
// 監聽端口
public void listen() {
try {
for (;;) {
selector.select();
Iterator<SelectionKey> iter = selector.selectedKeys()
.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
handleKey(key);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 處理事件
protected void handleKey(SelectionKey key) throws IOException {
if (key.isAcceptable()) { // 接收請求
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) { // 讀信息
SocketChannel channel = (SocketChannel) key.channel();
int count = channel.read(clientBuffer);
if (count > 0) {
clientBuffer.flip();
CharBuffer charBuffer = decoder.decode(clientBuffer);
System.out.println("Client >>" + charBuffer.toString());
SelectionKey wKey = channel.register(selector,
SelectionKey.OP_WRITE);
wKey.attach(new HandleClient());
} else
channel.close();
clientBuffer.clear();
} else if (key.isWritable()) { // 寫事件
SocketChannel channel = (SocketChannel) key.channel();
HandleClient handle = (HandleClient) key.attachment();
ByteBuffer block = handle.readBlock();
if (block != null)
channel.write(block);
else {
handle.close();
channel.close();
}
}
}
public static void main(String[] args) {
int port = 12345;
try {
NIOServer server = new NIOServer(port);
System.out.println("Listernint on " + port);
while (true) {
server.listen();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)客戶端(NIOClient.java)
package com.mcc.core.socket.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 無阻塞IO客戶端
*
* @author <a href="mailto:[email protected]">menergy</a>
* DateTime: 14-2-24 上午10:48
*/
public class NIOClient {
static int SIZE = 100;
static InetSocketAddress ip = new InetSocketAddress("localhost",12345);
static CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
static class Download implements Runnable {
protected int index;
public Download(int index) {
this.index = index;
}
public void run() {
try {
long start = System.currentTimeMillis();
SocketChannel client = SocketChannel.open();
client.configureBlocking(false);
Selector selector = Selector.open();
client.register(selector, SelectionKey.OP_CONNECT);
client.connect(ip);
ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
int total = 0;
FOR: for (;;) {
selector.select();
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
if (key.isConnectable()) {
SocketChannel channel = (SocketChannel) key.channel();
if (channel.isConnectionPending())
channel.finishConnect();
channel.write(encoder.encode(CharBuffer.wrap("Hello from " + index)));
channel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
int count = channel.read(buffer);
if (count > 0) {
total += count;
// 讀取的信息信息
final String readMessage = new String(buffer.array(), 0, count);
System.out.println("讀取信息:\n" + readMessage);
buffer.clear();
} else {
client.close();
break FOR;
}
}
}
}
double last = (System.currentTimeMillis() - start) * 1.0 / 1000;
System.out.println("Thread " + index + " downloaded " + total
+ "bytes in " + last + "s.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
ExecutorService exec = Executors.newFixedThreadPool(SIZE);
for (int index = 0; index < SIZE; index++) {
exec.execute(new Download(index));
}
exec.shutdown();
}
}