个人笔记TCP

发布于:2025-08-03 ⋅ 阅读:(12) ⋅ 点赞:(0)

TCP

TCP实现聊天

TcpClientDemo01

客户端

1.连接服务器Socket

2.发送消息

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
​
//客户端
public class TcpClientDemo01 {
    public static void main(String[] args) {
​
        Socket socket = null;
        OutputStream os = null;
        try {
            //1. 要知道服务器的地址,端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //2. 创建一个socket连接
            socket = new Socket(serverIP, port);
            //3. 发送消息 IO流
            os = socket.getOutputStream();
            os.write("1111111111111111".getBytes());
​
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
​
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

TcpServerDemo01

服务器

1.建立服务的端口

2.等待用户的连接accept

3.接受用户的消息

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
​
//服务端
public class TcpServerDemo01 {
    public static void main(String[] args)throws  Exception {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
​
        try {
            //1. 我得有一个地址
            serverSocket = new ServerSocket(9999);
​
            while (true){
                //2. 等待客户端连接过来
                socket = serverSocket.accept();
                //3. 读取客户端的消息
                is = socket.getInputStream();
                {
            /*
                byte[] buffer = new byte[1024];
                int len;
                while ((len=is.read(buffer))!=-1){
                    String msg = new String(buffer, 0, len);
                    System.out.println(msg);
                }
             */
                }
                //管道流
                baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    baos.write(buffer, 0, len);
                }
                System.out.println(baos.toString());
            }
​
​
​
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
​
        }
    }
}

文件上传

服务端

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
​
public class T1 {
    public static void main(String[] args) {
        int serverPort = 9001; // 修改为9001端口
        String outputFilePath = "d://receive.png";
​
        // 检查端口可用性
        if (!isPortAvailable(serverPort)) {
            System.err.println("错误:端口 " + serverPort + " 已被占用!请关闭其他应用或尝试其他端口。");
            System.exit(1);
        }
​
        try (ServerSocket serverSocket = new ServerSocket(serverPort)) {
            System.out.println("服务器已启动,监听端口: " + serverPort);
            System.out.println("等待客户端连接...");
​
            // 添加关闭钩子,确保服务器能关闭
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                System.out.println("服务器正在关闭...");
                try {
                    if (!serverSocket.isClosed()) {
                        serverSocket.close();
                    }
                    System.out.println("服务器已关闭");
                } catch (IOException e) {
                    System.err.println("关闭服务器时出错: " + e.getMessage());
                }
            }));
​
            // 接受客户端连接(无限循环支持多客户端)
            while (true) {
                try (Socket socket = serverSocket.accept();
                     InputStream is = socket.getInputStream();
                     FileOutputStream fos = new FileOutputStream(new File(outputFilePath))) {
​
                    System.out.println("客户端已连接: " + socket.getInetAddress());
​
                    // 接收文件并添加性能监控
                    byte[] buffer = new byte[1024];
                    int len;
                    long startTime = System.currentTimeMillis();
                    long totalBytes = 0;
​
                    // 读取客户端发送的数据并写入文件
                    while ((len = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, len);
                        totalBytes += len;
                    }
​
                    long endTime = System.currentTimeMillis();
​
                    System.out.println("文件接收完成,保存为: " + outputFilePath);
                    System.out.println("接收大小: " + totalBytes + " 字节,耗时: " + (endTime - startTime) + "ms");
​
                    // 发送确认消息给客户端
                    PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
                    writer.println("文件接收成功,大小: " + totalBytes + " 字节");
​
                    // 关闭输出流,但保持Socket打开让客户端读取响应
                    socket.shutdownOutput();
​
                } catch (IOException e) {
                    System.err.println("客户端连接处理异常: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            System.err.println("服务器启动失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
​
    // 检查指定端口是否可用的辅助方法
    private static boolean isPortAvailable(int port) {
        try (ServerSocket socket = new ServerSocket(port)) {
            return true;
        } catch (IOException e) {
            return false;
        }
    }
}

客户端

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
​
/**
 * TCP 客户端类,用于向指定服务器发送文件并接收服务器的响应
 */
public class T2 {
    public static void main(String[] args) {
        // 服务器的 IP 地址(本地回环地址,即本机)
        String serverHost = "127.0.0.1";
        // 服务器监听的端口(需与服务器端保持一致,这里是 9001)
        int serverPort = 9001;
        // 待发送的本地文件路径(需替换为实际文件路径)
        String filePath = "C:\\Users\\puton\\IdeaProjects\\demo1\\ocm.lyj.www\\Snake\\NET\\body.png";
​
        // 使用 try-with-resources 自动管理资源(Socket、输出流、文件输入流)
        try (
                // 1. 建立与服务器的 Socket 连接
                Socket socket = new Socket(InetAddress.getByName(serverHost), serverPort);
                // 2. 获取 Socket 的输出流(用于向服务器发送数据)
                OutputStream os = socket.getOutputStream();
                // 3. 创建文件输入流(用于读取本地文件)
                FileInputStream fis = new FileInputStream(new File(filePath))
        ) {
            // 连接成功后输出提示信息
            System.out.println("连接服务器成功: " + serverHost + ":" + serverPort);
​
            // 发送文件的缓冲区(每次读取 1024 字节)
            byte[] buffer = new byte[1024];
            // 记录每次读取的字节数
            int len;
            // 记录发送开始时间(用于计算耗时)
            long startTime = System.currentTimeMillis();
            // 记录发送的总字节数
            long totalBytes = 0;
​
            // 循环读取本地文件内容并发送到服务器
            // fis.read(buffer):从文件输入流读取数据到缓冲区,返回实际读取的字节数(-1 表示读取完毕)
            while ((len = fis.read(buffer)) != -1) {
                // 向服务器输出流写入数据(从缓冲区 0 位置开始,写入 len 字节)
                os.write(buffer, 0, len);
                // 累加总字节数
                totalBytes += len;
            }
​
            // 记录发送结束时间
            long endTime = System.currentTimeMillis();
​
            // 强制刷新输出流,确保所有数据都发送到服务器
            os.flush();
​
            // 关闭输出流(半关闭状态):告知服务器文件数据已发送完毕,但仍可接收服务器响应
            socket.shutdownOutput();
            // 输出发送结果:总大小和耗时
            System.out.println("文件发送完成,大小: " + totalBytes + " 字节,耗时: " + (endTime - startTime) + "ms");
​
            // 接收服务器的响应
            // 创建缓冲字符输入流(用于读取服务器发送的文本响应)
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String response;
            // 循环读取服务器响应(服务器关闭输出流后,readLine() 返回 null)
            while ((response = reader.readLine()) != null) {
                System.out.println("服务器响应: " + response);
            }
​
            // 所有操作完成后,提示连接关闭
            System.out.println("与服务器的连接已关闭");
​
        } catch (FileNotFoundException e) {
            // 捕获文件未找到异常(如本地文件路径错误)
            System.err.println("错误:文件未找到 - " + e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            // 捕获 IO 异常(如网络连接失败、读写错误等)
            System.err.println("IO异常: " + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            // 捕获其他未知异常
            System.err.println("发生未知错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Tomcat

服务端

  • 自定义S

  • Tomcat服务器S:java后台开发

客户端

  • 自定义C

  • 浏览器 B