Java中TCP通信的实现方法详解
作者:我有健康
0、TCP通信
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,
如果使用了 WireShark 工具,可以看到一次TCP连接建立时的整个过程。
1、单向通信
单向通信中,一方固定为信息发送方,另外一方则固定为信息的接收方。
1.1 单向通信中的服务端
服务端即为信息的接收方。
使用 ServerSocket 类创建服务端,并将服务的端口设置为 9527;
serverSocket.accept() 方法用于监听对 9527 端口的连接,该方法为阻塞式方法,当接收到数据后,程序才会继续向下执行,否则一直处于等待状态;
当接收到数据后,因是使用字节流传输,这里使用 使用 InputStreamReader 的转换流将字节数据转换为字符串,并使用 BufferedReader 进行读取和输出;
当服务端接收到客户端的请求后,需要向客户端发出响应数据,使用 PrintWriter 发送响应报文,需要使用 flush() 方法,将消息发出;
当客户端发出的消息为“再见”时,服务端即退出通信,关闭服务。
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { System.out.println("服务器启动!"); try { ServerSocket serverSocket = new ServerSocket(9527); Socket socket = serverSocket.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream()); System.out.println("接收客户端消息"); while (true){ String in = br.readLine(); System.out.println("接收到客户端发来的请求:" + in); if("再见".equals(in)){ break; } pw.print(in + "回报"); pw.flush(); } } catch (IOException e) { System.out.println("服务启动失败!"); e.printStackTrace(); } } }
启动后,服务端输出为:
服务器启动!
1.2 单向通信中的客户端
客户端即为信息的发送方。
- 创建 Socket 对象,
Socket("localhost", 9527)
和端口为 9527 的服务建立通信; - 接收和发送消息的方法,和服务端相同;
- 为了能够向服务端循环发送消息,使用了死循环,当用户输入“再见”时,终止循环;
- 使用 Scanner 对象接收键盘输入。
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) { try { Socket socket = new Socket("localhost", 9527); //读取输入流 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取输出流 PrintWriter pw = new PrintWriter(socket.getOutputStream()); //从键盘获取输入 Scanner scanner = new Scanner(System.in); while (true){ //从控制台获取向服务端发送的消息 String next = scanner.next(); pw.println(next); pw.flush(); String s = br.readLine(); System.out.println("收到服务器响应:" + s); if("再见".equals(next)){ break; } } } catch (IOException e) { e.printStackTrace(); } } }
1.3 建立通信
启动客户端后,并在客户端的控制台输入“你好”,观察服务端和客户端的控制台
在客户端的控制台输入“再见”,观察服务端和客户端的控制台
2、双向通信
双向通信中,双方都可以既是信息的发送方,也可以是信息的接收方。
2.1 双向通信中的服务端
在服务端设置发消息和收消息。
在服务端也使用了 Scanner ,用来接收控制台输入,并将其发送给客户端。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class Server { public static void main(String[] args) { try{ ServerSocket serverSocket = new ServerSocket(9528); Socket socket = serverSocket.accept(); //获取客户端请求 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取键盘输入 Scanner scanner = new Scanner(System.in); //发送消息到客户端 PrintWriter pw = new PrintWriter(socket.getOutputStream()); while (true){ String input = br.readLine(); System.out.println("收到客户端请求: " + input); String output = scanner.nextLine(); pw.println(output); pw.flush(); if("再见".equals(input)){ break; } } }catch (Exception e){ e.printStackTrace(); System.out.println("服务启动失败!"); } } }
2.2 双向通信中的客户端
在客户端设置发消息和收消息
import java.io.BufferedReader; 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) { try{ Socket socket = new Socket("127.0.0.1", 9528); //获取服务端响应 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取客户端用户输入 Scanner scanner = new Scanner(System.in); //向服务端发送请求 PrintWriter pw = new PrintWriter(socket.getOutputStream()); System.out.println("准备接收请求……"); while (true){ String output = scanner.next(); pw.println(output); pw.flush(); String input = br.readLine(); System.out.println("来自服务端的响应: " + input); if("再见".equals(output)){ break; } } }catch (Exception e){ e.printStackTrace(); } } }
2.3 建议通信
启动服务端及客户端,并在控制台输入内容:
存在的问题:
这样的通信,需要客户端发一次消息 -》 服务端回一次消息,如果客户端同时发送两条消息,就会导致消息不同步。
比如下边的情况:
这个问题可以先思考下,应该如何解决,后边将会给出解决方案。
总结
到此这篇关于Java中TCP通信的实现方法的文章就介绍到这了,更多相关Java TCP通信实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!