服务端代码:
package com.itbac.BIO; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务器 */ public class BIOServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服务器启动成功!"); while (!serverSocket.isClosed()) { Socket request = serverSocket.accept(); //阻塞 System.out.println("收到新连接:"+request.toString()); try { //获取输入流 InputStream inputStream = request.getInputStream(); //net 网络 + IO 输入输出流 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); String msg; while (null != (msg = reader.readLine())) { //readLine if (msg.length() == 0) { break; } System.out.println(msg); } System.out.println("收到数据,来自:"+request.toString()); } catch (IOException e) { e.printStackTrace(); } finally { try { request.close(); } catch (IOException e) { e.printStackTrace(); } } } serverSocket.close(); } }
客户端代码:
package com.itbac.BIO; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.nio.charset.Charset; import java.util.Scanner; /** * 客户端 */ public class BIOClient { //字符编码 private static Charset charset = Charset.forName("UTF-8"); public static void main(String[] args) throws IOException { //创建套接字 (服务端的ip,端口) Socket socket = new Socket("localhost", 8080); //获取输出流 OutputStream out = socket.getOutputStream(); //键盘输入 Scanner scanner = new Scanner(System.in); System.out.println("请输入:"); //获取下一行,阻塞 String msg = scanner.nextLine(); //写出,阻塞 out.write(msg.getBytes(charset)); scanner.close(); out.close(); } }
分别启动服务器,客户端,在客户端的控制台,键盘输入:12345
在服务端的控制台,看到以下输出:
服务器启动成功!
收到新连接:Socket[addr=/127.0.0.1,port=61238,localport=8080]
12345
收到数据,来自:Socket[addr=/127.0.0.1,port=61238,localport=8080]
信息解释:
服务器收到一个客户端连接,客户端地址addr ,客户端端口 port ,服务器的端口 localport
此时的服务器是单线程的,只能一条一条的接受数据。可以通过多线程的技术,改造一下。让代码可以支持多个客户端的消息。
package com.itbac.BIO; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class BIOServer1 { public static void main(String[] args) throws IOException { ExecutorService executorService = Executors.newCachedThreadPool(); ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服务器启动成功!"); while (!serverSocket.isClosed()) { Socket request = serverSocket.accept(); //阻塞 System.out.println("收到新连接:"+request.toString()); executorService.submit(() -> { try { //获取输入流 InputStream inputStream = request.getInputStream(); //net 网络 + IO 输入输出流 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); String msg; while (null != (msg = reader.readLine())) { //readLine if (msg.length() == 0) { break; } System.out.println(msg); } System.out.println("收到数据,来自:"+request.toString()); } catch (IOException e) { e.printStackTrace(); } finally { try { request.close(); } catch (IOException e) { e.printStackTrace(); } } }); } serverSocket.close(); } }
这样就可以同时处理多个客户端的请求。
通过启动多个客户端,可以一起想服务端发送数据了。其实浏览器也算是一个客户端,也可以和服务端交互。
浏览器使用的HTTP协议和服务端交互,服务端只要是也用这个协议就能响应数据给浏览器。
改造服务端代码:
package com.itbac.BIO; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //按照 HTTP协议响应数据 public class BIOServer2 { public static void main(String[] args) throws IOException { ExecutorService executorService = Executors.newCachedThreadPool(); ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服务器启动成功!"); while (!serverSocket.isClosed()) { Socket request = serverSocket.accept(); //阻塞 System.out.println("收到新连接:"+request.toString()); executorService.submit(() -> { try { //获取输入流 InputStream inputStream = request.getInputStream(); //net 网络 + IO 输入输出流 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); String msg; while (null != (msg = reader.readLine())) { //readLine if (msg.length() == 0) { break; } System.out.println(msg); } //获取输出流,设置http协议报文 OutputStream outputStream = request.getOutputStream(); //协议版本 响应状态码 响应状态 换行 outputStream.write("HTTP/1.1 200 OK ".getBytes()); //响应内容长度 换行,响应头部和主体之间要空一行,所以又换行。 outputStream.write("Contenet-Length:11 ".getBytes()); //响应主体内容 outputStream.write("Hello World ".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { request.close(); } catch (IOException e) { e.printStackTrace(); } } }); } serverSocket.close(); } }
这样,做到了浏览器和服务器的通信。