通过学习Http编程,更清晰的了解Java实现网络通信的底层逻辑与实现。
Server端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| package org.example;
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets;
public class ServerCase { private static final Logger log = LoggerFactory.getLogger(ServerCase.class); public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(6666)) { log.info("服务已启动"); for (;;) { Socket socket = serverSocket.accept(); log.info("connect from ="+socket.getRemoteSocketAddress()); Thread thread = new Handler(socket); thread.start(); } } catch (IOException e) { throw new RuntimeException(e); }
} }
class Handler extends Thread { private static final Logger log = LoggerFactory.getLogger(Handler.class);
private Socket socket; public Handler(Socket socket) { this.socket = socket; }
@Override public void run() { try (InputStream inputStream = this.socket.getInputStream()) { try (OutputStream outputStream = this.socket.getOutputStream()) { handle(inputStream, outputStream); } } catch (IOException e) { try { this.socket.close(); } catch (IOException ex) {
} log.error("client disconnected"); } }
private void handle (InputStream inputStream, OutputStream outputStream) throws IOException { var writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)); var reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); writer.write("Hello\n"); writer.flush(); for (;;) { String line = reader.readLine(); log.info("client say:" + line); if (line.equals("bye")) { writer.write("bye\n"); writer.flush(); break; } writer.write("yes\n"); writer.flush(); } } }
|
Client端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| package org.example;
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import java.io.*; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner;
public class ClientCase { private static final Logger log = LoggerFactory.getLogger(ClientCase.class);
public static void main(String[] args) { try (Socket socket = new Socket("localhost", 6666)) { log.info("connect from =" + socket.getRemoteSocketAddress()); try (InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream()) { handle(inputStream, outputStream); } } catch (IOException e) { log.error("Error during communication", e); } log.info("socket closed"); }
public static void handle(InputStream inputStream, OutputStream outputStream) throws IOException { var writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)); var reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); log.info("server say=" + reader.readLine()); Scanner scanner = new Scanner(System.in); for (;;) { log.info(">>>"); String s = scanner.nextLine(); writer.write(s); writer.newLine(); writer.flush();
var line = reader.readLine(); log.info("<<<" + line); if (line.equals("bye")) { break; } } } }
|
总结
总得来说,Java的网络通信通过Socket实现,Server端监听指定端口,Client端连接到Server端的端口,双方通过输入输出流进行通信。
需要特别注意的是,当利用BufferedWriter进行写入操作时,写完之后一定要跟上换行符 \n, 否则输入输出流会一直等待,这个小问题卡了我不少时间ORZ。