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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27605885/article/details/79548221

最近正在看这本书《看透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();
			}
		}
	}
}


猜你喜欢

转载自blog.csdn.net/qq_27605885/article/details/79548221