1.TCP通信原理
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网路虚拟链路,一旦建立虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。
Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信!
Java为客户端提供了Socket类,为服务器端提供了ServerSocket类。也就是说,客户端是通过Socket类实现的,而服务端是通过ServerSocket实现的。
2.TCP发送数据的步骤
1.创建客户端的Socket对象(Socket);
2.获取输出流,写数据;
3.使用打印流装饰输出流;
4.释放资源。
按照上述步骤编写的代码如下所示:
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class TCPClient {
public static void main(String[] args) throws IOException {
//创建客户端Socket对象
Socket socket = new Socket("127.0.0.1", 9999);
//获取输出流写数据
OutputStream outputStream = socket.getOutputStream();
PrintStream ps=new PrintStream(outputStream);
Scanner scanner = new Scanner(System.in);
String line=null;
while (true){
System.out.println("请说");
line=scanner.nextLine();
if("end".equals(line))
break;
ps.println(line);
}
//释放资源
scanner.close();
ps.close();
outputStream.close();
}
}
3.TCP接收数据的步骤
1.创建服务器端的Socket对象(SocketServer);
2.监听客户端的连接;
3.获取输入流,读数据,并显示在控制台;
4.使用BufferReader装饰输入流对象;
5.释放资源。
按照上述步骤编写的代码如下所示:
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 TCPServer {
public static void main(String[] args) throws IOException {
System.out.println("服务器已启动,正在监听客户端的连接");
ServerSocket serverSocket = new ServerSocket(9999);
//监听客户端的连接
Socket socket = serverSocket.accept();
//获取输入流
InputStream inputStream = socket.getInputStream();
//使用BufferedReader装饰输入流
BufferedReader br=new BufferedReader(new InputStreamReader(inputStream));
String line;
while((line=br.readLine())!=null){
System.out.println("服务器收到的信息:"+line);
}
//释放资源
br.close();
socket.close();
serverSocket.close();
}
}
4.效果展示
客户端执行效果演示:
服务器执行效果演示:
另外:需要注意的是,程序运行的时候需要先启动服务器端的程序,以便于服务器可以首先监听客户端的连接,否则运行程序会报服务器拒绝连接的错误
而由于一般Java程序运行的时候只有一个主线程和一个垃圾回收线程,因为我们程序的客户端的主线程一直在监听用户的输入数据,所以,如果想要实现客户端与服务器的双向聊天,需要使用到多线程来解决,有兴趣的小伙伴可以自己尝试一下。
5.实现双向聊天
通过前面的代码,我们已经使用TCP连接的三次握手建立了连接通道,所以,在上面代码的基础上实现双向的聊天就比较简单了。在这里,无论是客户端还是服务器,要想要接受消息,都需要一个线程不断的接受消息,所以,我们在这里需要使用到多线程来求解。具体代码如下所示:
客户端代码Client02.java
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client01 {
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",9999);
//创建一个新线程,使客户端接受服务器的消息
new Thread(()->{
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String info=null;
while((info=reader.readLine())!=null){
System.out.println("客户端收到的消息为:"+info);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
OutputStream outputStream = socket.getOutputStream();
PrintStream ps=new PrintStream(outputStream);
Scanner sc=new Scanner(System.in);
while(true){
String line = sc.nextLine();
ps.println(line);
}
}
}
服务器代码Server02.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server01 {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket=new ServerSocket(9999);
//监听
Socket socket = serverSocket.accept();
System.out.println("服务器监听已启动");
//创建一个新线程,让服务器向客户端发送消息
new Thread(()->{
try {
OutputStream outputStream = socket.getOutputStream();
PrintStream ps = new PrintStream(outputStream);
Scanner sc=new Scanner(System.in);
while(true){
String info = sc.nextLine();
ps.println(info);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
InputStream inputStream = socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(inputStream));
String line;
while((line=br.readLine())!=null){
System.out.println("服务器收到信息:"+line);
}
}
}
注意,这里我采用的多线程是直接new Thread(),在里面编写Lambda 表达式来实现功能!
效果展示: