Java TCP 网络通信编程

Posted Spring-_-Bear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java TCP 网络通信编程相关的知识,希望对你有一定的参考价值。

1. Java C-S 模式实现文件的网络传输,从客户端发送文件到服务器端,服务器端接收文件下载保存到本地并反馈消息给客户端。

  • 客户端:
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端:将文件发送到服务器端,并接收服务器发送的反馈信息
 *
 * @author Spring-_-Bear
 * @version 2021-11-01 20:24
 */
public class FileSendClient {
    public static void main(String[] args) {
        Socket socket = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader bufferedReader = null;
        BufferedInputStream bufferedInputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {
            // 读取到的字节数
            int readLen;
            // 文件大小
            int fileSize = 0;
            // 字节缓冲数组,加快文件读取速度
            byte[] buffer = new byte[1024];
            // 文件路径
            File filePath = new File("C:\\\\Users\\\\Admin\\\\Desktop\\\\BeFree.jpg");
            // 创建字节输出流,保存从文件读取到的二进制数据
            byteArrayOutputStream = new ByteArrayOutputStream();
            // 文件输入流
            bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));

            // 读取图片文件中的二进制内容,并将内容写进字节数组输出流
            System.out.println("文件读入中···");
            while ((readLen = bufferedInputStream.read(buffer)) != -1) {
                // 将从文件读取到的二进制数据写进字节数组输出流(byteArrayOutputStream)
                byteArrayOutputStream.write(buffer, 0, readLen);
                fileSize += readLen;
            }
            System.out.println("文件读入成功,文件大小为:" + fileSize + " bytes!");

            // 将得到的 byteArrayOutputStream 转换为一个字符数组
            byte[] array = byteArrayOutputStream.toByteArray();
            // 与服务器端建立连接
            socket = new Socket(InetAddress.getLocalHost(), 6666);
            // 获取输出流,将图片字节数组发送到服务器端
            outputStream = socket.getOutputStream();
            System.out.println("文件发送到服务器中···");
            outputStream.write(array);
            // 写入结束标志
            socket.shutdownOutput();
            System.out.println("文件发送到服务器成功!");

            // 接送服务器端发送的反馈信息并打印
            System.out.print("接收到的服务器信息:");
            inputStream = socket.getInputStream();
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            System.out.println(bufferedReader.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                inputStream.close();
                outputStream.close();
                bufferedReader.close();
                bufferedInputStream.close();
                byteArrayOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 服务端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器端:接收客户端发送的文件并下载保存到本地
 *
 * @author Spring-_-Bear
 * @version 2021-11-01 20:23
 */
public class FileReceiveServer {
    public static void main(String[] args) {
        Socket socket = null;
        InputStream inputStream = null;
        ServerSocket serverSocket = null;
        OutputStream outputStream = null;
        BufferedWriter bufferedWriter = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        try {
            // 监听端口,等待连接
            serverSocket = new ServerSocket(6666);
            System.out.println("服务器已启动,等待连接···");
            socket = serverSocket.accept();

            // 读取到的字节数
            int readLen;
            // 文件大小,单位为字节
            long fileSize = 0;
            // 缓冲字节数组,加快读取数组
            byte[] buffer = new byte[1024];
            // 获得输出流,从输入流中读取客户端发送过来的二进制数组信息
            inputStream = socket.getInputStream();
            // 字节数组输出流,保存从 inputStream 依次读出到的二进制数据
            byteArrayOutputStream = new ByteArrayOutputStream();

            // 从 inputStream 中读取数据
            System.out.println("文件读取中···");
            // 读取 inputStream 中的数据,并将数据写进 byteArrayOutputStream
            while ((readLen = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, readLen);
                fileSize += readLen;
            }
            System.out.println("文件读取成功,总大小为 " + fileSize + " bytes!");

            // 将 byteArrayOutputStream 中的数据转换为字节数组(文件二进制数据)
            byte[] array = byteArrayOutputStream.toByteArray();
            // 将最终得到的字节数组写进文件
            File filePath = new File("C:\\\\Users\\\\Admin\\\\Desktop\\\\temp.jpg");
            System.out.println("文件保存到本地中···");
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
            bufferedOutputStream.write(array);
            System.out.println("文件保存到本地成功!保存路径为:" + filePath);

            // 向客户端反馈文件下载保存成功信息
            outputStream = socket.getOutputStream();
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            System.out.print("发送反馈信息到客户端··· ");
            bufferedWriter.write("文件接收成功,下载保存完成!");
            bufferedWriter.newLine();
            bufferedWriter.flush();
            System.out.println("消息发送成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                inputStream.close();
                outputStream.close();
                serverSocket.close();
                bufferedWriter.close();
                byteArrayOutputStream.close();
                bufferedOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2. 客户端发出下载文件请求,服务端响应客户端请求并将文件发送给客户端,客户端接收服务端发送的文件并下载保存到本地

  • 客户端:
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 服务端:发送想要下载的文件名称到客户端,得到客户端回应并将文件保存到本地
 *
 * @author Spring-_-Bear
 * @version 2021-11-02 09:58
 */
public class FileClient {
    byte[] fileData = null;

    Socket socket = null;
    InputStream inputStream = null;
    OutputStream outputStream = null;
    BufferedOutputStream bufferedOutputStream = null;
    Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        FileClient client = new FileClient();

        try {
            client.socket = new Socket(InetAddress.getLocalHost(), 9999);
            client.sendFileNameToServer();
            client.receiveFileData();
            client.saveFile();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.socket.close();
                client.inputStream.close();
                client.outputStream.close();
                client.bufferedOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送想要下载的文件名到服务器端
     */
    public void sendFileNameToServer() {
        try {
            System.out.print("请输入您想要下载的文件名(含文件拓展名):");
            String choice = scanner.next();
            outputStream = socket.getOutputStream();
            outputStream.write(choice.getBytes(StandardCharsets.UTF_8));
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 接收从服务端传送的数据
     */
    public void receiveFileData() {
        try {
            int readLen = 0;
            byte[] buf = new byte[1024];
            inputStream = socket.getInputStream();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            System.out.println("正在接收服务器传输的文件···");
            while ((readLen = inputStream.read(buf)) != -1) {
                byteArrayOutputStream.write(buf, 0, readLen);
            }
            socket.shutdownInput();
            fileData = byteArrayOutputStream.toByteArray();
            System.out.println("文件接收成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将从服务器端接收到的文件保存到本地
     */
    public void saveFile() {
        try {
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\\\Users\\\\Admin\\\\Desktop\\\\temp.jpg"));
            System.out.println("正在将文件保存到本地···");
            bufferedOutputStream.write(fileData);
            System.out.println("文件保存到本地完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//    /**
//     * 读取服务端发送的文件名并显示到控制台
//     */
//    public void receiveFilesName() {
//        bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//        System.out.println("正在接收服务端发送的文件目录···");
//        String fileName = "";
//        System.out.println(bufferedReader.readLine());
//        while ((fileName = bufferedReader.readLine()) != null) {
//            System.out.println(fileName);
//        }
//        System.out.println("接收服务端发送的文件目录成功!");
//    }
}
  • 服务端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 * 服务端:将客户端请求的文件传输到客户端
 *
 * @author Spring-_-Bear
 * @version 2021-11-02 09:57
 */
public class FileServer {
    byte[] fileData = null;
    String requestFileName = null;
    ArrayList<String> fileNameList = new ArrayList<>();
    File filePath = new File("C:\\\\Users\\\\Admin\\\\Desktop\\\\sourceFile");

    Socket socket = null;
    ServerSocket serverSocket = null;
    InputStream inputStream = null;
    BufferedInputStream bufferedInputStream = null;

    public static void main(String[] args) {
        FileServer server = new FileServer();
        server.createAndReadFiles();
        server.startServer();
        server.receiveRequestNameFromClient();
        server.readFileFromDisk();
        server.transferFileToClient();
        try {
            server.socket.close();
            server.serverSocket.close();
            server.inputStream.close();
            server.bufferedInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取指定路径下的所有文件
     */
    public void createAndReadFiles() {
        System.out.println("正在进行文件夹初始化···");
        // 若文件夹不存在,则先创建文件夹
        if (!(filePath.exists() && filePath.isDirectory())) {
            filePath.mkdirs();
        }

        // 读取文件夹中的所有文件,并将文件名存进集合
        File[] files = filePath.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                fileNameList.add(file.getName());
            }
        }
        System.out.println("初始化完成!");
    }

    /**
     * 启动服务器
     */
    public void startServer() {
        try {
            serverSocket = new ServerSocket(9999);
            System.out.println("服务器已启动,等待连接···");
            socket = serverSocket.accept();
            System.out.println("服务端 - 客户端建立连接成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取客户端请求的文件名
     */
    public void receiveRequestNameFromClient() {
        try {
            int readLen;
            byte以上是关于Java TCP 网络通信编程的主要内容,如果未能解决你的问题,请参考以下文章

Java-Web学习-Java基础-网络编程(TCP和UDP)附TCP实现通信

java网络编程TCP/UDP笔记

Java网络编程实现简单通信含代码(狂神说)

Java网络编程之TCP通信

阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第2节 TCP协议_3_TCP通信的客户端代码实现

Java的TCP网络编程