Java中bio编程
网络编程(Socket)概念
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个 socket。 建立网络通信连接至少要一个端口号。socket 本质是编程接口(API),对 TCP/IP 的封装, TCP/IP 也要提供可供程序员做网络开发所用的接口,这就是 Socket 编程接口;HTTP 是轿车, 提供了封装或者显示数据的具体形式;Socket 是发动机,提供了网络通信的能力。
Socket 连接步骤
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三 个步骤:服务器监听,客户端请求,连接确认。【如果包含数据交互+断开连接,那么一共是 五个步骤】
(1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连 接的状态,实时监控网络状态。
(2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的 套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套 接字的地址和端口号,然后就向服务器端套接字提出连接请求。
(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求, 它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端, 一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接 收其他客户端套接字的连接请求。
Java 中的 Socket
在 java.net 包是网络编程的基础类库。其中 ServerSocket 和 Socket 是网络编程的基础类 型。ServerSocket 是服务端应用类型。Socket 是建立连接的类型。当连接建立成功后,服务 器和客户端都会有一个 Socket 对象示例,可以通过这个 Socket 对象示例,完成会话的所有 操作。 对于一个完整的网络连接来说,Socket 是平等的,没有服务器客户端分级情况
什么是同步和异步
同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发 IO 操作并 等待或者轮询的去查看 IO 操作是否就绪,而异步是指用户进程触发 IO 操作以后便开始做自 己的事情,而当 IO 操作已经完成的时候会得到 IO 完成的通知。
什么是阻塞和非阻塞
阻塞和非阻塞是针对于进程在访问数据的时候,根据 IO 操作的就绪状态来采取的不同 方式,说白了是一种读取或者写入操作方法的实现方式,阻塞方式下读取或者写入函数将一 直等待,而非阻塞方式下,读取或者写入方法会立即返回一个状态值。
BIO 编程
Blocking IO: 同步阻塞的编程方式。
BIO 编程方式通常是在 JDK1.4 版本之前常用的编程方式。编程实现过程为:首先在服务 端启动一个 ServerSocket 来监听网络请求,客户端启动 Socket 发起网络请求,默认情况下 ServerSocket 回建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等 待或遭到拒绝。
且建立好的连接,在通讯过程中,是同步的。在并发处理效率上比较低。大致结构如下:
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就 需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可 以通过线程池机制改善
BIO 方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4 以前的唯一选择.
使用线程池机制改善后的 BIO 模型图如下:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) { String host = null; int port = 0; if (args.length > 2) { host = args[0]; port = Integer.parseInt(args[1]); } else { host = "127.0.0.1"; port = 9999; } Socket socket = null; BufferedReader reader = null; PrintWriter writer = null; Scanner s = new Scanner(System.in); try { socket = new Socket(host, port); String message = null; reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); writer = new PrintWriter(socket.getOutputStream(), true); while (true) { message = s.nextLine(); if (message.equals("exit")) { break; } writer.println(message); writer.flush(); System.out.println(reader.readLine()); } } catch (Exception e) { e.printStackTrace(); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } socket = null; if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } reader = null; if (writer != null) { writer.close(); } writer = null; } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { int port = genPort(args); ServerSocket server = null; try { server = new ServerSocket(port); System.out.println("server started!"); while (true) { Socket socket = server.accept(); new Thread(new Handler(socket)).start(); } } catch (Exception e) { e.printStackTrace(); } finally { if (server != null) { try { server.close(); } catch (IOException e) { e.printStackTrace(); } } server = null; } } static class Handler implements Runnable { Socket socket = null; public Handler(Socket socket) { this.socket = socket; } @Override public void run() { BufferedReader reader = null; PrintWriter writer = null; try { reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")); String readMessage = null; while (true) { System.out.println("server reading... "); if ((readMessage = reader.readLine()) == null) { break; } System.out.println(readMessage); writer.println("server recive : " + readMessage); writer.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } socket = null; if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } reader = null; if (writer != null) { writer.close(); } writer = null; } } } private static int genPort(String[] args) { if (args.length > 0) { try { return Integer.parseInt(args[0]); } catch (NumberFormatException e) { return 9999; } } else { return 9999; } } }
线程池改造后的代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Server { public static void main(String[] args) { int port = genPort(args); ServerSocket server = null; //定长线程 ExecutorService service = Executors.newFixedThreadPool(50); try { server = new ServerSocket(port); System.out.println("server started!"); while (true) { Socket socket = server.accept(); service.execute(new Handler(socket)); } } catch (Exception e) { e.printStackTrace(); } finally { if (server != null) { try { server.close(); } catch (IOException e) { e.printStackTrace(); } } server = null; } } static class Handler implements Runnable { Socket socket = null; public Handler(Socket socket) { this.socket = socket; } @Override public void run() { BufferedReader reader = null; PrintWriter writer = null; try { reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")); String readMessage = null; while (true) { System.out.println("server reading... "); if ((readMessage = reader.readLine()) == null) { break; } System.out.println(readMessage); writer.println("server recive : " + readMessage); writer.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } socket = null; if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } reader = null; if (writer != null) { writer.close(); } writer = null; } } } private static int genPort(String[] args) { if (args.length > 0) { try { return Integer.parseInt(args[0]); } catch (NumberFormatException e) { return 9999; } } else { return 9999; } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String[] args) { String host = null; int port = 0; if(args.length > 2){ host = args[0]; port = Integer.parseInt(args[1]); }else{ host = "127.0.0.1"; port = 9999; } Socket socket = null; BufferedReader reader = null; PrintWriter writer = null; Scanner s = new Scanner(System.in); try { socket = new Socket(host, port); String message = null; reader = new BufferedReader( new InputStreamReader(socket.getInputStream(), "UTF-8")); writer = new PrintWriter( socket.getOutputStream(), true); while(true){ message=s.nextLine(); if(message.equals("exit")) break; writer.println(message); writer.flush(); System.out.println(reader.readLine()); } } catch (Exception e) { e.printStackTrace(); }finally{ if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } socket = null; if(reader != null){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } reader = null; if(writer != null){ writer.close(); } writer = null; } } }