TCP服务器
他也涉及到两个核心的类
ServerSocket
Socket
这里注意:
UDP协议无连接,类似发微信,直接发就行
TCP协议有连接,类似打电话,要接通才能通话。
这里依然用回显服务器模式来体会TCP服务器:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpEchoServer {
private ServerSocket serverSocket = null;
public TcpEchoServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void start() throws IOException {
System.out.println("服务器启动");
//进入主循环
while (true) {
//获取内核连接
Socket clientSocket = serverSocket.accept();
//处理连接
processConnection(clientSocket);
}
}
private void processConnection(Socket clientSocket) {
System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),
clientSocket.getPort());
//获取clientSocket中的流对象
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()))) {
//客户端和服务器有时并不是只交互一次
//这时服务器处理的方式
//(短连接)1.一个连接客户端和服务器只交互一次完毕之后就断开连接
//(长连接)2.一个连接中客户端和服务器交互N次,直到满足一定条件再断开连接
//当客户端断开连接,循环就结束啦
//当断开连接,readLine或者write就会触发异常
//此处为长连接
while (true) {
//客户端发送的数据必须按行
String request = bufferedReader.readLine();
String response = process(request);
bufferedWriter.write(response+"\n");
System.out.printf("[%s:%d] req: %s;resp %s\n",clientSocket.getInetAddress().toString(),
clientSocket.getPort(),request,response);
}
} catch (IOException e) {
System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress().toString(),
clientSocket.getPort());
}
}
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
TcpEchoServer server = new TcpEchoServer(9090);
server.start();
}
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class TcpEchoClient {
//a.启动客户端(和服务器建立连接)
//b.进入主循环
//1.读取用户输入内容
//2.构造请求发送给服务器
//3.读取响应
//4.吧响应显示在界面
private Socket socket = null;
public TcpEchoClient(String serverIp,int serverPort) throws IOException {
socket = new Socket(serverIp,serverPort);
}
public void start() {
System.out.println("客户端启动");
Scanner scanner = new Scanner(System.in);
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
while (true) {
System.out.print("->");
String request = scanner.nextLine();
if (request.equals("exit")) {
break;
}
//构造请求并发送
bufferedWriter.write(request+"\n");
//读取响应
//请求和响应格式不一定相同
String response = bufferedReader.readLine();
System.out.println(response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
此时有一个问题:
这里我们就考虑用线程池来解决这个问题:
节省了频繁创建和销毁线程的开销。