💤
💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨
💤
客户端代码
public class TcpEchoClient {
private String serverIp;
private int serverPort;
private Socket socket = null;
public TcpEchoClient(String serverIp, int serverPort) throws IOException {
this.serverIp = serverIp;
this.serverPort = serverPort;
// 让socket创建的同时,就和服务器尝试建立了连接
socket = new Socket(serverIp,serverPort);
}
public void start(){
Scanner scanner = new Scanner(System.in);
try(InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream()){
while(true){
// 1.从键盘上,读取用户的内容
System.out.println("-> ");
String request = scanner.nextLine();
if ("goodbye".equals(request)){
break;
}
// 2.把这个读取的内容构成请求,发送给服务器
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.print(request);
// 3.从服务器读取响应并解析
Scanner response = new Scanner(inputStream);
String responseStrings= response.next();
// 4.把结果显示到界面上
String log = String.format("request: %s; response: %s",request,responseStrings);
System.out.println(log);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",8080);
tcpEchoClient.start();
}
}
服务器代码
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("Server start!");
while(true){
// UDP的服务器进入主循环,就直接尝试receiver读取请求了
// 但是TCP是有连接的,先要做的是,建立好连接
// 当服务器运行的时候,当前是否有客户端来建立连接,不确定
// 如果客户端没有建立连接了,accept就会阻塞等待
// TODO: 2021/10/26 如果有多个客户端对同一个服务器尝试建立连接会发送什么?
// 如果有客户端建立连接了,此时accept就会返回一个socket对象
// 进一步的服务器和客户端之间的交互,就交给client Socket
Socket clientSocket = serverSocket.accept();
processConnection(clientSocket);
}
}
private void processConnection(Socket clientSocket) throws IOException {
// 处理一个连接,在这个连接中可能会涉及客户端和服务器之间的多次交互
String log = String.format("[%s:%d] 客户端上线!",clientSocket.getInetAddress().toString(),
clientSocket.getPort());
System.out.println(log);
// 输入
try(InputStream inputStream = clientSocket.getInputStream();
// 输出
OutputStream outputStream = clientSocket.getOutputStream()) {
while (true) {
// 1.读取请求并解析
// 可以直接通过 inputStream 的read 把数据读到一个byte[]上,然后再转成一个String
// 但是比较麻烦,还可以借助Scanner 来完成工作
Scanner scanner = new Scanner(inputStream);
if (!scanner.hasNext()){
log = String.format("[%s:%d] 客户端下线",clientSocket.getInetAddress().toString(),
clientSocket.getPort());
System.out.println(log);
break;
}
String request = scanner.next();
System.out.println(request);
// 2.根据请求计算响应
String response = process(request);
// 3.把响应写回给客户端
PrintWriter writer = new PrintWriter(outputStream);
writer.print(response);
log = String.format("[%s:%d] req: %s; resp: %s",clientSocket.getInetAddress(),
clientSocket.getPort(),request,response);
System.out.println(log);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 当前的clientSocket生命周期,不是跟随整个程序,而是和连接相关
// 因此就需要每个连接结束,都要进行关闭
// 否则随着连接的增多,这个socket文件就可能出现资源泄漏的情况
clientSocket.close();
}
}
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
TcpEchoServer tcpEchoServer = new TcpEchoServer(8080);
tcpEchoServer.start();
}
当我把服务器和客户端启动之后
Server start!
[/127.0.0.1:61497] 客户端上线!
服务器和客户端显示正常运行
但客户端发送请求后:
客户端
->
AKA
服务器没有做出任何的响应,这时候说明代码中存在bug
猜测:
?1.客户端可能没有正确的发送数据
?2.服务器可能没有正确读取数据
回到代码上
我们发送请求使用的是:
printWriter.print(request);
收取请求使用的是:
String request = scanner.next();
?这里分析一些scanner.next()方法
? next()在读取到什么字符的时候才能返回?
? 空白字符 如 空格、制表符、换行符、翻页符
所以为了解决这个问题我们就需要才外加空白字符
方便起见,发送请求使用:
printWriter.println(request);
当修改完成后,再次运行
当我们在客户端进行输入的时候,发现服务器还是收不到客户端的请求
这又是哪里出了问题???
回顾我们学习File和IO的时候,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。
因此我们的请求是不是被放到了缓冲区?
为了验证一下
我们在发送请求的下面加上这一行代码,用来刷新缓冲区
printWriter.print(request);
printWriter.flush();
再次运行
客户端
->
AKA
request: AKA; response: AKA
服务器
Server start!
[/127.0.0.1:61835] 客户端上线!
AKA
[/127.0.0.1:61835] req: AKA; resp: AKA
正常运行
|