netty入门一回顾阻塞IO

本文通过Java代码示例介绍了基于BIO的Socket服务端和客户端实现,展示了如何处理并发请求。服务端使用固定线程池处理连接,客户端并发发起请求并接收响应,展示了BIO在并发场景下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

准备抽时间深入学习netty,在此之前先回顾BIO 扫清NIO盲点,本篇先回顾一下BIO

传统的socket编程是BIO即阻塞,因此为了对并发的支持,传统的BIO模型只能每个线程都封装一个socket,以达到支持并发的效果

下面我们上一段模拟向一个服务端并发发起请求的代码,基于Socket阻塞IO模型实现

服务端SocketServer:

package cn.qu.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
服务器端:
① 创建ServerSocket对象,绑定监听端口
② 通过accept()方法监听客户端请求
③ 连接建立后,通过输入流读取客户端发送的请求信息
④ 通过输出流向客户端发送乡音信息
⑤ 关闭相关资源
*/
public class SocketServer {

	final static int port = 8081;
	private static ServerSocket serverSocket = null;
	private static ExecutorService fixedThreadExecutor = Executors.newFixedThreadPool(2);

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

	public static void start() {
		try {
			serverSocket = new ServerSocket(port);
			System.out.println("........SocketServer.start..........");
			while (true) {
				Socket socket = serverSocket.accept();
				fixedThreadExecutor.execute(() -> {
					try {
						Thread.sleep(50);
						String addr = socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
						System.out.println(addr + "  发起请求");
						System.out.println(Thread.currentThread().getName() + "->" + System.currentTimeMillis());
						BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
						String line = "";
						while (!"".equals((line = reader.readLine())) && line != null) {
							System.out.print(line);
						}
						System.out.println();
						System.out.println();
						socket.shutdownInput();
						OutputStream out = socket.getOutputStream();
						out.write("来自SocketServer response".getBytes());
						socket.shutdownOutput();
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						try {
							if(!socket.isClosed()) {								
								socket.close();
							}
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

}

以上代码大致逻辑介绍如下:

1.构建ServerSocket绑定到8081端口

2.循环监听ServerSocket

3.如果有请求建立socket连接,则异步处理

4.打印请求内容,取消输入阻塞

5.对请求进行回应,取消输出阻塞

6.关闭socket。

客户端SocketClient:

package cn.qu.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/*
Socket通信的步骤
① 创建ServerSocket和Socket
② 打开连接到Socket的输入/输出流
③ 按照协议对Socket进行读/写操作
④ 关闭输入输出流、关闭Socket
*/
public class SocketClient {

	final static int listenerPort = 8081;
	final static String listenerInet4Address = "127.0.0.1";
	
	public static void main(String[] args) {
		for(int i = 0; i < 4; i ++) {			
			start(8091 + i, "SocketClient say hello");
		}
	}

	private static void start(int port, String data) {
		Socket socket = null;
		try {
			socket = new Socket(listenerInet4Address, listenerPort, InetAddress.getByName(listenerInet4Address), port);
			OutputStream out = socket.getOutputStream();
			out.write(data.getBytes());
			socket.shutdownOutput();
			BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			String line = "";
			while (!"".equals((line = reader.readLine())) && line != null) {
				System.out.print(line);
			}
			System.out.println();
			socket.shutdownInput();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(!socket.isClosed()) {					
					socket.close();
				}
			} catch (IOException e) {
			}			
		}
		
	}

}

以上代码大致逻辑介绍如下:

1.并发创建socket连接,4个参数:远程服务IP,远程服务端口,当前服务IP,当前服务端口

2.向服务端发起请求,并关闭输出阻塞

3.接收服务端的响应,并关闭输入阻塞

4.关闭socket连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值