C/S architecture file upload case based on TCP protocol

The demo code

/** * File upload client, read local file, upload to server ** data source: local file * destination: server ** Step: * 1. Create client object * 2. Get local file input stream read into Byte array * 3. Upload the socket file output stream to the server * 4. Obtain the information returned by the server from the socket file input stream, and print * 5. Close the resource */
public class Client {
    public static void main(String[] args) throws IOException {
        //1. Create client objects
        Socket socket = new Socket("127.0.0.1".8888);

        //2. Get the local file input stream and read it into the Byte array
        File file = new File("E:\\data\\project\\tcp-study\\clientImg\\1596592777(1).jpg");
        FileInputStream is = new FileInputStream(file);
        byte[] bytes = new byte[1024];
        int len=0;

        //3. Obtain the socket file output stream and upload it to the server
        OutputStream os = socket.getOutputStream();
        while((len=is.read(bytes))! = -1){
            os.write(bytes,0,len);
        }

        //4. Obtain the socket file input stream and print the information returned by the server
        InputStream socketInputStream = socket.getInputStream();
        while((len=socketInputStream.read(bytes))! = -1){
            System.out.println(new String(bytes, 0, len));
        }

        //5. Close the resourcesocketInputStream.close(); os.close(); is.close(); socket.close(); }}Copy the code
/** * File upload server, obtain the file uploaded by the client, save in the local ** Step: * 1. Get server object * 2. Get socket object * 3. Get client input stream according to socket * 4. Read the input stream, while using the local output stream output to the local folder to save * 5. Get the socket output stream and output the saved information to the client. 6. Close the resource
public class Server {
    public static void main(String[] args) throws IOException {
        //1. Obtain the server object
        ServerSocket serverSocket = new ServerSocket(8888);
        //2. Obtain the socket object
        Socket socket = serverSocket.accept();
        //3. Obtain the client input stream based on the socket
        InputStream socketInputStream = socket.getInputStream();

        //4. Read the input stream and use the local output stream to save the output to the local folder
        byte[] bytes = new byte[1024];
        int len =0;
        File file = new File("E:\\data\\project\\tcp-study\\serverImg");
        // If the folder does not exist, create it
        if(! file.exists()){ file.createNewFile(); } FileOutputStream fileOutputStream =new FileOutputStream(file+File.separator+"1.jpg");
        while((len=socketInputStream.read(bytes))! = -1){
            fileOutputStream.write(bytes,0,len);
        }

        //5. Obtain the socket output stream and output the saved information to the client
        OutputStream socketOutputStream = socket.getOutputStream();
        socketOutputStream.write("Saved successfully".getBytes());

        //6. Close the resourcesocketOutputStream.close(); socketInputStream.close(); fileOutputStream.close(); socket.close(); serverSocket.close(); }}Copy the code

While (len=is.read(bytes)) in the client code, while (len=is.read(bytes))! = 1)

The client reads to the end of the file, but does not tell the server that it is finished. As a result, the server keeps waiting and does not send a message indicating that the save is successful. As a result, the client is also waiting, so both the client and the server block.

Solve the problem of program I/O block caused by the client not sending the conclusion

While (len=is.read(bytes)) on the client! =-1), use socket.shutdownOutput(); Tell the server it’s over.

/** * File upload client, read local file, upload to server ** data source: local file * destination: server ** Step: * 1. Create client object * 2. Get local file input stream read into Byte array * 3. Upload the socket file output stream to the server * 4. Obtain the information returned by the server from the socket file input stream, and print * 5. Close the resource */
public class Client {
    public static void main(String[] args) throws IOException {
        //1. Create client objects
        Socket socket = new Socket("127.0.0.1".8888);

        //2. Get the local file input stream and read it into the Byte array
        File file = new File("E:\\data\\project\\tcp-study\\clientImg\\1596592777(1).jpg");
        FileInputStream is = new FileInputStream(file);
        byte[] bytes = new byte[1024];
        int len=0;

        //3. Obtain the socket file output stream and upload it to the server
        OutputStream os = socket.getOutputStream();
        while((len=is.read(bytes))! = -1){
            os.write(bytes,0,len);
        }
        
        // Tell the server that it is finished
        socket.shutdownOutput();

        
        //4. Obtain the socket file input stream and print the information returned by the server
        InputStream socketInputStream = socket.getInputStream();
        while((len=socketInputStream.read(bytes))! = -1){
            System.out.println(new String(bytes, 0, len));
        }

        //5. Close the resourcesocketInputStream.close(); os.close(); is.close(); socket.close(); }}Copy the code

Optimizing the server code

  1. Images save naming rules to prevent duplication of names
  2. The optimization server can only accept the image once and then terminate, using a while loop without closing the resource
/** * File upload server, obtain the file uploaded by the client, save in the local ** Step: * 1. Get server object * 2. Get socket object * 3. Get client input stream according to socket * 4. Read the input stream, while using the local output stream output to the local folder to save * 5. Get the socket output stream and output the saved information to the client */
public class Server {
    public static void main(String[] args) throws IOException {
        //1. Obtain the server object
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true) {//2. Obtain the socket object
            Socket socket = serverSocket.accept();
            //3. Obtain the client input stream based on the socket
            InputStream socketInputStream = socket.getInputStream();

            //4. Read the input stream and use the local output stream to save the output to the local folder
            byte[] bytes = new byte[1024];
            int len =0;
            // Custom naming rules to prevent duplicate names
            String fileName="laowang"+System.currentTimeMillis()+ new Random().nextInt(9999) +".jpg";
            File file = new File("E:\\data\\project\\tcp-study\\serverImg");
            // If the folder does not exist, create it
            if(! file.exists()){ file.createNewFile(); } FileOutputStream fileOutputStream =new FileOutputStream(file+File.separator+fileName);
            while((len=socketInputStream.read(bytes))! = -1){
                fileOutputStream.write(bytes,0,len);
            }

            //5. Obtain the socket output stream and output the saved information to the client
            OutputStream socketOutputStream = socket.getOutputStream();
            socketOutputStream.write(("Saved successfully,url :"+file.getCanonicalPath()+fileName).getBytes()); }}}Copy the code

The server side uses multi-threading to improve efficiency

/** * File upload server, obtain the file uploaded by the client, save in the local ** Step: * 1. Get server object * 2. Get socket object * 3. Get client input stream according to socket * 4. Read the input stream, while using the local output stream output to the local folder to save * 5. Get the socket output stream and output the saved information to the client */
public class Server {
    public static void main(String[] args) throws IOException {
        //1. Obtain the server object
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true) {//2. Obtain a socket object, and start a thread to execute it
            Socket socket = serverSocket.accept();
            // Use multithreading for efficiency
            new Thread(()->{
                try {
                    //3. Obtain the client input stream based on the socket
                    InputStream socketInputStream = socket.getInputStream();
                    //4. Read the input stream and use the local output stream to save the output to the local folder
                    byte[] bytes = new byte[1024];
                    int len =0;
                    // Custom naming rules to prevent duplicate names
                    String fileName="laowang"+System.currentTimeMillis()+ new Random().nextInt(9999) +".jpg";
                    File file = new File("E:\\data\\project\\tcp-study\\serverImg");
                    // If the folder does not exist, create it
                    if(! file.exists()){ file.createNewFile(); } FileOutputStream fileOutputStream =new FileOutputStream(file+File.separator+fileName);
                    while((len=socketInputStream.read(bytes))! = -1){
                        fileOutputStream.write(bytes,0,len);
                    }

                    //5. Obtain the socket output stream and output the saved information to the client
                    OutputStream socketOutputStream = socket.getOutputStream();
                    socketOutputStream.write(("Saved successfully,url :"+file.getCanonicalPath()+fileName).getBytes());

                    / / 6. Closed
                    socketOutputStream.close();
                    fileOutputStream.close();
                    socketInputStream.close();
                    socket.close();
                }catch(Exception e){ System.out.println(e); } }).start(); }}}Copy the code

Based on Tcp protocol B/S architecture browser access image request small case

/** * TCP based B/S server */
public class Server {
    public static void main(String[] args) throws IOException {
        //1. Obtain the server object
        ServerSocket serverSocket = new ServerSocket(8888);

        //2. Obtain the client socket object
        Socket socket = serverSocket.accept();

        //3. Read the request sent by the client
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len =0;
        while((len=is.read(bytes))! = -1){
            System.out.println(new String(bytes,0,len));
        }

        // Close the resourceis.close(); serverSocket.close(); socket.close(); }}Copy the code

The browser initiates the request: http://localhost:8888/tcp-study/web/1.jpg

Results:

As you can see, the packet read out is like this, we can intercept the circled string, write the corresponding file as client IO stream, complete!

The code is as follows:

/** ** the TCP protocol B/S server */
public class Server {
    public static void main(String[] args) throws IOException {
        //1. Obtain the server object
        ServerSocket serverSocket = new ServerSocket(8888);

        while (true) {//2. Obtain the client socket object
            Socket socket = serverSocket.accept();
            new Thread(()->{
                try {
                    //3. Read the request sent by the client
                    // Read a line, that is, the file input stream, wrapped as a character stream
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    // Read a line
                    String line = null;
                    try {
                        line = reader.readLine();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // Split by space, then remove the initial /, resulting in tcp-study/web/1.jpg
                    String[] split = line.split("");
                    String url=split[1].substring(1);
                    System.out.println("Access to the url:"+url);

                    // Use the local stream to read the file in this path and write it to the client stream
                    FileInputStream is = new FileInputStream(url);
                    byte[] bytes = new byte[1024];
                    int len=0;

                    // Write the HTTP response header to be parsed by the browser
                    OutputStream os = socket.getOutputStream();
                    os.write("HTTP / 1.1 200 OK \ r \ n".getBytes());
                    os.write("Content-Type:text/html\r\n".getBytes());
                    os.write("\r\n".getBytes());

                    while((len=is.read(bytes))! = -1) {/ / write out
                        os.write(bytes,0,len);
                    }

                    // Close the resource
                    socket.close();
                    os.close();
                    is.close();
                    reader.close();
                }catch(Exception e){ System.out.println(e); } }).start(); }}}Copy the code

Request: http://localhost:8888/web/hello.html

Results: