案例——TCP上传图片

时间:2024-01-25 15:36:18

TCP上传图片

  继续做一个TCP的相关案例,在客户端上传一张图片到服务端,服务端收到图片后,给客户端回馈上传成功信息。

实现细节:

  • 对于一些文件的读取,若文件偏大,可以始用缓冲区去读取和写入,可以提高效率
  • 服务端面向的是很多用户,所以必须要开线程来接收
  • 如果同一个用户上传多张图片则有可能文件名重复,所以要对文件名做处理,具体在代码处有注释
  • 客户端图片上传完成后需要给服务端发送结束信息,s.shutdownOutput();
    就像是写入了一个终止符一样

客户端

需要在上传结束的时候写入终止符告诉服务端上传结束,可以双方约定一个终止的符号,也可以用shutdownOutput()方法来传递结束信息

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class UploadPicClient {

    public static void main(String[] args) throws IOException {
        System.out.println("上传图片客户端启动...");
        
        //1、创建socket
        Socket s = new Socket("127.233.24.3", 10018);
        
        //2、读取源图片
        File picFile = new File("D:\\forio\\download.jpg");
        BufferedInputStream fis = new BufferedInputStream(new FileInputStream(picFile));
        
        //3、目的:socket输出流,发送到服务端
        OutputStream out = s.getOutputStream();
        byte[] buf = new byte[1024];
        
        int len = 0;
        while((len = fis.read(buf)) != -1)
        {
            out.write(buf, 0, len);
        }
        
        //告诉服务端   图片发送完成,不要在等着读了
        s.shutdownOutput();
        
        //读取上传成功字样
        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String info = in.readLine();
        System.out.println(info);
        
        //关闭
        fis.close();
        s.close();
    }
}

服务端

服务端需要多线程接收多个客户的上传信息,对于有可能存在的文件名重复,添加(1)(2)(3)...加以区分

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadPicServer {

    public static void main(String[] args) throws IOException {
        System.out.println("上传图片服务端启动...");

        // 创建ServerSocket
        ServerSocket ss = new ServerSocket(10018);

        while (true) {
            // 获取客户端
            Socket s = ss.accept();

            // 实现多个客户端并发上传,服务器端必须启动做个线程来完成
            new Thread(new UploadPic(s)).start();

        }
    }
}

class UploadPic implements Runnable {

    private Socket s;

    public UploadPic(Socket s) {
        super();
        this.s = s;
    }

    @Override
    public void run() {

        try {

            String ip = s.getInetAddress().getHostAddress();
            System.out.println(ip + "connected...");

            // 写图片数据到文件的输出流
            File dir = new File("D:\\forio\\photo");
            // 为了避免重名覆盖,通过给重名文件进行编号
            int count = 1;
            File picFile = new File(dir, ip + "(" + count + ")" + ".jpg");
            while (picFile.exists()) {
                count++;
                picFile = new File(dir, ip + "(" + count + ")" + ".jpg");
            }

            FileOutputStream fos = new FileOutputStream(picFile);

            // 读取客户端发来的数据
            InputStream in = s.getInputStream();
            byte[] buf = new byte[1024];
            int len = 0;

            while ((len = in.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            // 给客户端一个回馈信息
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            out.write("上传成功!"); // 写完需要刷新一下,或者关闭流

            // 关闭资源
            out.close();
            fos.close();
            s.close();

        } catch (Exception e) {

        }

    }

}

结果演示

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述