网络编程之BIO

服务端代码:

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();
    }
}

这样,做到了浏览器和服务器的通信。

原文地址:https://www.cnblogs.com/itbac/p/12002248.html