1. 程式人生 > >看透SpringMVC系列(一)Java中的Socket

看透SpringMVC系列(一)Java中的Socket

最近正在看這本書《看透SpringMVC:原始碼分析與實戰》,作者韓路彪。

推薦用微信讀書APP,下面基本照抄上面的,覺得不過癮可以去自己看

Java中的Socket分為兩種:普通socket和NioSocket。

同步阻塞IO(JAVA BIO): 

    同步並阻塞,伺服器實現模式為一個連線一個執行緒,即客戶端有連線請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不做任何事情會造成不必要的執行緒開銷,當然可以通過執行緒池機制改善。 

123

456

//服務端
public static void main(String[] args) throws Exception {
		PrintWriter pw = null;
		ServerSocket server = null;
		Socket socket = null;
		BufferedReader bufferedReader = null;
		try {
			server = new ServerSocket(8080);
			socket = server.accept();//這裡阻塞
			InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
			bufferedReader = new BufferedReader(inputStreamReader);
			String receivedMsg = bufferedReader.readLine();
			System.out.println("從客戶端接收到資料:" + receivedMsg);
			//接下來服務端回傳資料給客戶端
			pw = new PrintWriter(socket.getOutputStream());
			pw.println("已經收到資料了");
			pw.flush();
		} finally {
			if(pw != null)
				pw.close();
			if(server != null)
				server.close();
			if(socket != null)
				socket.close();
			if(pw != null)
				pw.close();
			if(bufferedReader != null)
				bufferedReader.close();
		}
	}
//客戶端
	public static void main(String[] args) throws Exception {
		Socket socket = null;
		BufferedReader bufferedReader = null;
		PrintWriter pw = null;
		try {
			socket= new Socket("127.0.0.1", 8080);
			InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
			//接下來服務端回傳資料給客戶端
			pw = new PrintWriter(socket.getOutputStream());
			pw.println("客戶端傳送資料了");
			pw.flush();
			bufferedReader = new BufferedReader(inputStreamReader);
			String receivedMsg = bufferedReader.readLine();
			System.out.println("從服務端接收到資料:" + receivedMsg);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(pw != null)
				pw.close();
			if(socket != null)
				socket.close();
			if(pw != null)
				pw.close();
			if(bufferedReader != null)
				bufferedReader.close();
		}


同步非阻塞IO(Java NIO) : 同步非阻塞,伺服器實現模式為一個請求一個執行緒,即客戶端傳送的連線請求都會註冊到多路複用器上,多路複用器輪詢到連線有I/O請求時才啟動一個執行緒進行處理。使用者程序也需要時不時的詢問IO操作是否就緒,這就要求使用者程序不停的去詢問。 

非同步阻塞IO(Java NIO):  

   此種方式下是指應用發起一個IO操作以後,不等待核心IO操作的完成,等核心完成IO操作以後會通知應用程式,這其實就是同步和非同步最關鍵的區別,同步必須等待或者主動的去詢問IO是否完成,那麼為什麼說是阻塞的呢?因為此時是通過select系統呼叫來完成的,而select函式本身的實現方式是阻塞的,而採用select函式有個好處就是它可以同時監聽多個檔案控制代碼(如果從UNP的角度看,select屬於同步操作。因為select之後,程序還需要讀寫資料),從而提高系統的併發性! 

nio部分後面補上


package nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;

public class NIOClient {//客戶端

	public static void main(String[] args) {
		ByteBuffer buffer = ByteBuffer.allocate(1024);
        SocketChannel socketChannel = null;
        try
        {
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("127.0.0.1",8080));
 
            if(socketChannel.finishConnect())
            {
                int i=0;
                while(true)
                {
                    TimeUnit.SECONDS.sleep(1);
                    String info = "I'm "+i+++"-th information from client";
                    buffer.clear();
                    buffer.put(info.getBytes());
                    buffer.flip();
                    while(buffer.hasRemaining()){
                        System.out.println(buffer);
                        socketChannel.write(buffer);
                    }
                }
            }
        }
        catch (IOException | InterruptedException e)
        {
            e.printStackTrace();
        }
        finally{
            try{
                if(socketChannel!=null){
                    socketChannel.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }

	}

}

package 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;

public class NIOServer {//服務端

	private static final int BUF_SIZE = 1024;
	private static final int PORT = 8080;
	private static final int TIMEOUT = 3000;

	public static void main(String[] args) {
		selector();
	}

	public static void handleAccept(SelectionKey key) throws IOException {
		ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
		SocketChannel sc = ssChannel.accept();
		sc.configureBlocking(false);
		sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
	}

	public static void handleRead(SelectionKey key) throws IOException {
		SocketChannel sc = (SocketChannel) key.channel();
		ByteBuffer buf = (ByteBuffer) key.attachment();
		long bytesRead = sc.read(buf);
		while (bytesRead > 0) {
			buf.flip();
			while (buf.hasRemaining()) {
				System.out.print((char) buf.get());
			}
			System.out.println();
			buf.clear();
			bytesRead = sc.read(buf);
		}
		if (bytesRead == -1) {
			sc.close();
		}
	}

	public static void handleWrite(SelectionKey key) throws IOException {
		ByteBuffer buf = (ByteBuffer) key.attachment();
		buf.flip();
		SocketChannel sc = (SocketChannel) key.channel();
		while (buf.hasRemaining()) {
			sc.write(buf);
		}
		buf.compact();
	}

	public static void selector() {
		Selector selector = null;
		ServerSocketChannel ssc = null;
		try {
			selector = Selector.open();
			ssc = ServerSocketChannel.open();
			ssc.socket().bind(new InetSocketAddress(PORT));
			ssc.configureBlocking(false);
			ssc.register(selector, SelectionKey.OP_ACCEPT);

			while (true) {
				if (selector.select(TIMEOUT) == 0) {
					System.out.println("==");
					continue;
				}
				Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
				while (iter.hasNext()) {
					SelectionKey key = iter.next();
					if (key.isAcceptable()) {
						handleAccept(key);
					}
					if (key.isReadable()) {
						handleRead(key);
					}
					if (key.isWritable() && key.isValid()) {
						handleWrite(key);
					}
					if (key.isConnectable()) {
						System.out.println("isConnectable = true");
					}
					iter.remove();
				}
			}

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (selector != null) {
					selector.close();
				}
				if (ssc != null) {
					ssc.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}