java implements uploading files to server and client

  • 2020-12-21 18:03:40
  • OfStack

JAVA writes a server and client that can upload files, the details are as follows

The service side


class Server 
{ 
 public static void main(String[] args) throws Exception 
 { 
 // Set up the server side Socket 
 ServerSocket ss = new ServerSocket(10005); 
 // Receiving client Socket 
 Socket fileLoaderSocket = ss.accept(); 

 // Print connection information  
 String ip = fileLoaderSocket.getInetAddress().getHostAddress(); 
 System.out.println(ip + "...conncected"); 

 // Receive the file and save it  
 InputStream in = fileLoaderSocket.getInputStream(); 
 // Instantiate object fileSave
 OutputStream fileSave = new FileOutputStream("E:\\3.mp3"); 
 // Build array buf
 byte[] buf = new byte[1024]; 
 int len = 0; 
 // Determine if you read to the end of the file 
 while((len=in.read(buf)) != -1) 
  { 
  fileSave.write(buf, 0, len); 
  // The refresh 
  fileSave.flush(); 
  } 
 // Returns file copy status information  
 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fileLoaderSocket.getOutputStream())); 
 out.write(" File upload successful "); 
 // The refresh 
 out.flush(); 
 // Resources to shut down  
 ss.close(); 
 fileLoaderSocket.close(); 
 fileSave.close(); 
 } 
} 

Client:


class Client
{ 
 public static void main(String[] args) throws Exception 
 { 
 // To establish Socket service  
 Socket fileLoaderSocket = new Socket("168.168.168.94", 10005); 
 // Read the file locally from the client , And write socket Of the output stream  
 OutputStream out = fileLoaderSocket.getOutputStream(); 
 // Instantiate object fileReader
 InputStream fileRead = new FileInputStream("G:\\2.mp3"); 
 // Build array 
 byte[] buf = new byte[1024]; 
 int len = 0; 
 // Determine if you read to the end of the file 
 while((len=fileRead.read(buf)) != -1)
  { 
  out.write(buf, 0, len); 
  } 
 // Tell the server that the file has been transferred  
 fileLoaderSocket.shutdownOutput(); 
 // Get feedback from the server  
 BufferedReader in = new BufferedReader(new InputStreamReader(fileLoaderSocket.getInputStream())); 
 String serverBack = in.readLine(); 
 System.out.println(serverBack); 
 // Resources to shut down  
 fileLoaderSocket.close(); 
 fileRead.close(); 
 } 
} 

The following procedure is directly copied from elsewhere for learning reference:

Java Socket programming

For Java Socket programming, there are two concepts, one is ServerSocket and the other is Socket. A connection is established between the server and the client through Socket, after which they can communicate. First of all, ServerSocket will listen on the server side for a port. When it finds that the client has Socket to try to connect to it, it will request the connection of accept and set up a corresponding Socket on the server side to communicate with it. This gives you two Socket, one client and one server.
The communication between Socket is very simple. The server writes to the output stream of Socket, and the client can read the corresponding content through the input stream of Socket. Socket and Socket are bidirectional, so the client can also write to the corresponding Socket output stream, and then the server can read the corresponding Socket input stream. Here are some examples of how the server communicates with the client:

1. Client write server read

Server Java code


public class Server { 

 public static void main(String args[]) throws IOException { 
 // For simplicity, all exception information is thrown out  
 int port = 8899; 
 // define 1 a ServerSocket Listen on port 8899 on  
 ServerSocket server = new ServerSocket(port); 
 //server Try to receive other Socket Is the connection request, server the accept The method is blocking  
 Socket socket = server.accept(); 
 // After we have established a connection with the client, we can get it socket the InputStream , and read the information sent from the client.  
 Reader reader = new InputStreamReader(socket.getInputStream()); 
 char chars[] = new char[64]; 
 int len; 
 StringBuilder sb = new StringBuilder(); 
 while ((len=reader.read(chars)) != -1) { 
  sb.append(new String(chars, 0, len)); 
 } 
 System.out.println("from client: " + sb); 
 reader.close(); 
 socket.close(); 
 server.close(); 
 } 

} 

The operation of the server reading data from InputStream's InputStream is also blocking. If no data is read from the input stream, the program will stay there until the client writes data to the output stream of Socket or closes the output stream of Socket. Of course, the same is true for Socket on the client side. At the end of the operation, remember to close the corresponding resource, that is, close the corresponding IO stream and Socket.

Client Java code


public class Client { 

 public static void main(String args[]) throws Exception { 
 // For simplicity, all exceptions are thrown straight out  
 String host = "127.0.0.1"; // The server to connect to IP address  
 int port = 8899; // The listener port of the server to which you want to connect  
 // Establish a connection with the server  
 Socket client = new Socket(host, port); 
 // After establishing the connection, you can write data to the server  
 Writer writer = new OutputStreamWriter(client.getOutputStream()); 
 writer.write("Hello Server."); 
 writer.flush();// Remember when you're done flush 
 writer.close(); 
 client.close(); 
 } 

} 

For the client to inside Socket output stream to write data is passed to the server to note 1 point, if the write operation after the closing of the program is not corresponding to the output stream, but for other blocking type of operation (such as from an input stream to read data), remember to flush1, only in this way can the server received the client sends data, otherwise it may cause the sides of infinite wait for each other. We'll talk about this later when we talk about both client and server reading and writing simultaneously.

2. Both client and server read and write at the same time

As mentioned earlier, Socket communicates with each other bi-directional.it can receive and send data at the same time.

Server Java code


public class Server { 

 public static void main(String args[]) throws IOException { 
 // For simplicity, all exception information is thrown out  
 int port = 8899; 
 // define 1 a ServerSocket Listen on port 8899 on  
 ServerSocket server = new ServerSocket(port); 
 //server Try to receive other Socket Is the connection request, server the accept The method is blocking  
 Socket socket = server.accept(); 
 // After we have established a connection with the client, we can get it socket the InputStream , and read the information sent from the client.  
 Reader reader = new InputStreamReader(socket.getInputStream()); 
 char chars[] = new char[64]; 
 int len; 
 StringBuilder sb = new StringBuilder(); 
 while ((len=reader.read(chars)) != -1) { 
  sb.append(new String(chars, 0, len)); 
 } 
 System.out.println("from client: " + sb); 
 // When you've finished writing 1 other  
 Writer writer = new OutputStreamWriter(socket.getOutputStream()); 
 writer.write("Hello Client."); 
 writer.flush(); 
 writer.close(); 
 reader.close(); 
 socket.close(); 
 server.close(); 
 } 

} 

In the above code, we first read the data sent by the client from the input stream, then we write the data into the output stream to the client, and then close the corresponding resource file. In fact, the code may not work the way we expected, because reading data from the input stream is a blocking operation, and in the while loop above, the body of the loop is executed when the data is read, otherwise it will block, and subsequent writes will never be executed. The while loop will not stop until the client's Socket block is turned off. The solution to this problem is that the while loop needs to jump out conditionally. Throughout the above code, the only things that change are the length of the fetch len and the read data. len is no longer usable, and the only thing that works is the read data. In this case, we usually agree on an end tag. When the data sent by the client contains an end tag, it means that the current data has been sent. At this time, we can break out of the loop. The improved code would look like this:

Java code


public class Server { 

 public static void main(String args[]) throws IOException { 
 // For simplicity, all exception information is thrown out  
 int port = 8899; 
 // define 1 a ServerSocket Listen on port 8899 on  
 ServerSocket server = new ServerSocket(port); 
 //server Try to receive other Socket Is the connection request, server the accept The method is blocking  
 Socket socket = server.accept(); 
 // After we have established a connection with the client, we can get it socket the InputStream , and read the information sent from the client.  
 Reader reader = new InputStreamReader(socket.getInputStream()); 
 char chars[] = new char[64]; 
 int len; 
 StringBuilder sb = new StringBuilder(); 
 String temp; 
 int index; 
 while ((len=reader.read(chars)) != -1) { 
  temp = new String(chars, 0, len); 
  if ((index = temp.indexOf("eof")) != -1) {// encounter eof The end of the reception  
  sb.append(temp.substring(0, index)); 
  break; 
  } 
  sb.append(temp); 
 } 
 System.out.println("from client: " + sb); 
 // When you've finished writing 1 other  
 Writer writer = new OutputStreamWriter(socket.getOutputStream()); 
 writer.write("Hello Client."); 
 writer.flush(); 
 writer.close(); 
 reader.close(); 
 socket.close(); 
 server.close(); 
 } 

} 

In the above code, when the server reads the end tag sent by the client, known as "eof", the data is received, the loop is terminated, and subsequent code can proceed again.

Client Java code


public class Client { 

 public static void main(String args[]) throws Exception { 
 // For simplicity, all exceptions are thrown straight out  
 String host = "127.0.0.1"; // The server to connect to IP address  
 int port = 8899; // The listener port of the server to which you want to connect  
 // Establish a connection with the server  
 Socket client = new Socket(host, port); 
 // After establishing the connection, you can write data to the server  
 Writer writer = new OutputStreamWriter(client.getOutputStream()); 
 writer.write("Hello Server."); 
 writer.flush(); 
 // Read after you write  
 Reader reader = new InputStreamReader(client.getInputStream()); 
 char chars[] = new char[64]; 
 int len; 
 StringBuffer sb = new StringBuffer(); 
 while ((len=reader.read(chars)) != -1) { 
  sb.append(new String(chars, 0, len)); 
 } 
 System.out.println("from server: " + sb); 
 writer.close(); 
 reader.close(); 
 client.close(); 
 } 

} 

In the above code, we first sent a piece of data to the server, and then read the data returned by the server, which may cause program 1 to hang in there and never jump out of the while loop during the process of reading like the previous server 1. This code, in conjunction with the first section of the server, just makes it possible for us to analyze that the server is always there to receive data, never jumping out of the while loop, so that no later server will return data to the client, and the client will never receive the data returned by the server. The solution is as shown in section 2 of the server. After the client sends the data, write an end tag to the output stream to tell the server that the data has been sent. Similarly, after the server returns the data, it also sends a tag to tell the client. The modified client code should look like this:

Java code


public class Client { 

 public static void main(String args[]) throws Exception { 
 // For simplicity, all exceptions are thrown straight out  
 String host = "127.0.0.1"; // The server to connect to IP address  
 int port = 8899; // The listener port of the server to which you want to connect  
 // Establish a connection with the server  
 Socket client = new Socket(host, port); 
 // After establishing the connection, you can write data to the server  
 Writer writer = new OutputStreamWriter(client.getOutputStream()); 
 writer.write("Hello Server."); 
 writer.write("eof"); 
 writer.flush(); 
 // Read after you write  
 Reader reader = new InputStreamReader(client.getInputStream()); 
 char chars[] = new char[64]; 
 int len; 
 StringBuffer sb = new StringBuffer(); 
 String temp; 
 int index; 
 while ((len=reader.read(chars)) != -1) { 
  temp = new String(chars, 0, len); 
  if ((index = temp.indexOf("eof")) != -1) { 
  sb.append(temp.substring(0, index)); 
  break; 
  } 
  sb.append(new String(chars, 0, len)); 
 } 
 System.out.println("from server: " + sb); 
 writer.close(); 
 reader.close(); 
 client.close(); 
 } 

} 

We usually use this kind of client to send data to the server, and the server receives the data and then returns the corresponding results to the client. It's just that the relationship between the client and the server is no longer one-to-one, but the following situation where multiple clients correspond to one server.

3. Multiple clients are connected to one server

As in the two previous examples, the server receives a request from one client and ends up receiving no more requests from other clients, which often fails to meet our requirements. Usually we do this:

Java code


public class Server { 

 public static void main(String args[]) throws IOException { 
 // For simplicity, all exception information is thrown out  
 int port = 8899; 
 // define 1 a ServerSocket Listen on port 8899 on  
 ServerSocket server = new ServerSocket(port); 
 while (true) { 
  //server Try to receive other Socket Is the connection request, server the accept The method is blocking  
 Socket socket = server.accept(); 
  // After we have established a connection with the client, we can get it socket the InputStream , and read the information sent from the client.  
 Reader reader = new InputStreamReader(socket.getInputStream()); 
  char chars[] = new char[64]; 
  int len; 
  StringBuilder sb = new StringBuilder(); 
  String temp; 
  int index; 
  while ((len=reader.read(chars)) != -1) { 
  temp = new String(chars, 0, len); 
  if ((index = temp.indexOf("eof")) != -1) {// encounter eof The end of the reception  
  sb.append(temp.substring(0, index)); 
  break; 
  } 
  sb.append(temp); 
  } 
  System.out.println("from client: " + sb); 
  // When you've finished writing 1 other  
 Writer writer = new OutputStreamWriter(socket.getOutputStream()); 
  writer.write("Hello Client."); 
  writer.flush(); 
  writer.close(); 
  reader.close(); 
  socket.close(); 
 } 
 } 

} 

In the above code we use an infinite loop in which ServerSocket calls its accept method to try to receive a connection request from the client. When no request is received, the program blocks here until it receives a connection request from the client, then communicates with the currently established client, and then executes the loop body to try again to receive a new connection request. This allows our ServerSocket to receive connection requests from all clients and communicate with them. This implements a simple pattern of one server communicating with multiple clients.
In the example above, although a server is implemented to communicate with multiple clients, there is still a problem. In the above example, our server processes the client's connection request synchronously, and each time it receives a connection request from the client, it communicates with the current client before processing the next connection request. This can seriously affect the performance of the program in the case of high concurrency, so we can change it to the following asynchronous processing and client communication:

Java code


public class Server { 

 public static void main(String args[]) throws IOException { 
 // For simplicity, all exception information is thrown out  
 int port = 8899; 
 // define 1 a ServerSocket Listen on port 8899 on  
 ServerSocket server = new ServerSocket(port); 
 while (true) { 
  //server Try to receive other Socket Is the connection request, server the accept The method is blocking  
  Socket socket = server.accept(); 
  // Each received 1 a Socket establishing 1 I have a new thread to process it  
  new Thread(new Task(socket)).start(); 
 } 
 } 

 /** 
 *  To deal with Socket The request of  
 */ 
 static class Task implements Runnable { 

 private Socket socket; 

 public Task(Socket socket) { 
  this.socket = socket; 
 } 

 public void run() { 

  try { 

  handleSocket(); 
  } catch (Exception e) { 
  e.printStackTrace(); 
  } 
 } 

 /** 
 *  With the client Socket communicate  
 * @throws Exception 
 */ 
 private void handleSocket() throws Exception { 
  Reader reader = new InputStreamReader(socket.getInputStream()); 
  char chars[] = new char[64]; 
  int len; 
  StringBuilder sb = new StringBuilder(); 
  String temp; 
  int index; 
  while ((len=reader.read(chars)) != -1) { 
  temp = new String(chars, 0, len); 
  if ((index = temp.indexOf("eof")) != -1) {// encounter eof The end of the reception  
  sb.append(temp.substring(0, index)); 
  break; 
  } 
  sb.append(temp); 
  } 
  System.out.println("from client: " + sb); 
  // When you've finished writing 1 other  
 Writer writer = new OutputStreamWriter(socket.getOutputStream()); 
  writer.write("Hello Client."); 
  writer.flush(); 
  writer.close(); 
  reader.close(); 
  socket.close(); 
 } 

 } 

} 

In the above code, each time ServerSocket receives a new Socket connection request, a new thread is created to communicate with the current Socket, thus achieving the asynchronous process of communicating with client Socket.
When receiving data from Socket's InputStream, reading one dot at a time like the above is too complicated. Sometimes we will use BufferedReader to read one line at a time, such as:

Java code


class Client
{ 
 public static void main(String[] args) throws Exception 
 { 
 // To establish Socket service  
 Socket fileLoaderSocket = new Socket("168.168.168.94", 10005); 
 // Read the file locally from the client , And write socket Of the output stream  
 OutputStream out = fileLoaderSocket.getOutputStream(); 
 // Instantiate object fileReader
 InputStream fileRead = new FileInputStream("G:\\2.mp3"); 
 // Build array 
 byte[] buf = new byte[1024]; 
 int len = 0; 
 // Determine if you read to the end of the file 
 while((len=fileRead.read(buf)) != -1)
  { 
  out.write(buf, 0, len); 
  } 
 // Tell the server that the file has been transferred  
 fileLoaderSocket.shutdownOutput(); 
 // Get feedback from the server  
 BufferedReader in = new BufferedReader(new InputStreamReader(fileLoaderSocket.getInputStream())); 
 String serverBack = in.readLine(); 
 System.out.println(serverBack); 
 // Resources to shut down  
 fileLoaderSocket.close(); 
 fileRead.close(); 
 } 
} 
0

Note at this point that BufferedReader's readLine method reads 1 line at a time. This method is blocked until it reads 1 line. When will readLine read 1 line? Until the program encounters a newline character or the corresponding stream terminator, the readLine method does not recognize that it has reached 1 line, ends its block, and allows the program to proceed. So we in the use of BufferedReader readLine 1 need to remember when reading data in the corresponding output stream 1 need to write a newline (automatically mark to end the end of the stream, readLine can identify), after writing a newline 1 will remember if the output stream is not close the case immediately remember flush1, such data will only be truly written from the buffer. Corresponding to the above code, our client program should write:

Java code


class Client
{ 
 public static void main(String[] args) throws Exception 
 { 
 // To establish Socket service  
 Socket fileLoaderSocket = new Socket("168.168.168.94", 10005); 
 // Read the file locally from the client , And write socket Of the output stream  
 OutputStream out = fileLoaderSocket.getOutputStream(); 
 // Instantiate object fileReader
 InputStream fileRead = new FileInputStream("G:\\2.mp3"); 
 // Build array 
 byte[] buf = new byte[1024]; 
 int len = 0; 
 // Determine if you read to the end of the file 
 while((len=fileRead.read(buf)) != -1)
  { 
  out.write(buf, 0, len); 
  } 
 // Tell the server that the file has been transferred  
 fileLoaderSocket.shutdownOutput(); 
 // Get feedback from the server  
 BufferedReader in = new BufferedReader(new InputStreamReader(fileLoaderSocket.getInputStream())); 
 String serverBack = in.readLine(); 
 System.out.println(serverBack); 
 // Resources to shut down  
 fileLoaderSocket.close(); 
 fileRead.close(); 
 } 
} 
1

4. Set the timeout

Suppose there is a requirement that our client needs to get XX information from the server through Socket and present it to the user on the page. We know that Socket is blocking when it reads the data, and if it doesn't read the data, it will block 1 until it gets there. We certainly cannot allow this to happen when synchronizing requests, which requires us to control the blocking interruption after the request reaches a certain time, so that the program can continue to run. Socket provides us with an setSoTimeout() method to set the timeout in milliseconds for the received data. Socket throws 1 SocketTimeoutException when the timeout is set to be greater than 0 and Socket has not received the returned data after that time.
Suppose we want to control our client to break the block without reading the data 10 seconds after it has started reading the data we can do this:

Java code


class Client
{ 
 public static void main(String[] args) throws Exception 
 { 
 // To establish Socket service  
 Socket fileLoaderSocket = new Socket("168.168.168.94", 10005); 
 // Read the file locally from the client , And write socket Of the output stream  
 OutputStream out = fileLoaderSocket.getOutputStream(); 
 // Instantiate object fileReader
 InputStream fileRead = new FileInputStream("G:\\2.mp3"); 
 // Build array 
 byte[] buf = new byte[1024]; 
 int len = 0; 
 // Determine if you read to the end of the file 
 while((len=fileRead.read(buf)) != -1)
  { 
  out.write(buf, 0, len); 
  } 
 // Tell the server that the file has been transferred  
 fileLoaderSocket.shutdownOutput(); 
 // Get feedback from the server  
 BufferedReader in = new BufferedReader(new InputStreamReader(fileLoaderSocket.getInputStream())); 
 String serverBack = in.readLine(); 
 System.out.println(serverBack); 
 // Resources to shut down  
 fileLoaderSocket.close(); 
 fileRead.close(); 
 } 
} 
2

5. Receive data garbled

In this case, the server or client receives Chinese scrambled code because the code used to send the data is not the same as the code used to receive the data. For example, there is a piece of server-side code like this:

Java code


public class Server { 

 public static void main(String args[]) throws IOException { 
 // For simplicity, all exception information is thrown out  
 int port = 8899; 
 // define 1 a ServerSocket Listen on port 8899 on  
 ServerSocket server = new ServerSocket(port); 
 while (true) { 
  //server Try to receive other Socket Is the connection request, server the accept The method is blocking  
  Socket socket = server.accept(); 
  // Each received 1 a Socket establishing 1 I have a new thread to process it  
  new Thread(new Task(socket)).start(); 
 } 
 } 

 /** 
 *  To deal with Socket The request of  
 */ 
 static class Task implements Runnable { 

 private Socket socket; 

 public Task(Socket socket) { 
  this.socket = socket; 
 } 

 public void run() { 
  try { 
  handleSocket(); 
  } catch (Exception e) { 
  e.printStackTrace(); 
  } 
 } 

 /** 
 *  With the client Socket communicate  
 * @throws Exception 
 */ 
 private void handleSocket() throws Exception { 
  BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK")); 
  StringBuilder sb = new StringBuilder(); 
  String temp; 
  int index; 
  while ((temp=br.readLine()) != null) { 
  System.out.println(temp); 
  if ((index = temp.indexOf("eof")) != -1) {// encounter eof The end of the reception  
  sb.append(temp.substring(0, index)); 
  break; 
  } 
  sb.append(temp); 
  } 
  System.out.println(" The client : " + sb); 
  // When you've finished writing 1 other  
 Writer writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8"); 
  writer.write(" Hello, client. "); 
  writer.write("eof\n"); 
  writer.flush(); 
  writer.close(); 
  br.close(); 
  socket.close(); 
 } 
 } 
} 

I messed up a little bit here for the test. In the above server-side code, we explicitly defined the use of GBK encoding to read data when defining the input stream and es171EN-8 encoding to send data when defining the output stream. If the data sent by the client is not sent in GBK, the data received by the server is likely to be confused; Similarly, if the client does not receive data with the encoding that the server sends, i.e. UTF-8 encoding, to receive data, it is very likely that the data will be scrambled. Therefore, for the above server-side code, in order to enable our program to read the data sent by the other side without any messy code situation, our client should look like this:

Java code


class Client
{ 
 public static void main(String[] args) throws Exception 
 { 
 // To establish Socket service  
 Socket fileLoaderSocket = new Socket("168.168.168.94", 10005); 
 // Read the file locally from the client , And write socket Of the output stream  
 OutputStream out = fileLoaderSocket.getOutputStream(); 
 // Instantiate object fileReader
 InputStream fileRead = new FileInputStream("G:\\2.mp3"); 
 // Build array 
 byte[] buf = new byte[1024]; 
 int len = 0; 
 // Determine if you read to the end of the file 
 while((len=fileRead.read(buf)) != -1)
  { 
  out.write(buf, 0, len); 
  } 
 // Tell the server that the file has been transferred  
 fileLoaderSocket.shutdownOutput(); 
 // Get feedback from the server  
 BufferedReader in = new BufferedReader(new InputStreamReader(fileLoaderSocket.getInputStream())); 
 String serverBack = in.readLine(); 
 System.out.println(serverBack); 
 // Resources to shut down  
 fileLoaderSocket.close(); 
 fileRead.close(); 
 } 
} 
4

This article has been compiled into Java Upload operation Skills Summary, welcome to learn to read.


Related articles: