客户端除了套接字的输出流,还有读取本地文件的输入流,还有套接字的输入流来读取来自服务端的反馈信息。
服务端也同样有三流:套接字的输入、输出流,写入上传目标文件的输出流。
客户端读取本地文件的所有数据后,需要使用套接字的shutdownOutput()来通知服务端套接字的输出流已到末尾。
服务端为了能为多人提供上传功能,需要使用多线程实现并发连接。
Client端:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; public class UploadClient { public static void main(String[] args) { // TODO Auto-generated method stub String server_addr = "192.168.0.124"; int server_port = 8888; Socket send_sock = null; FileInputStream local_read = null; try { // 1.客户端套接字 send_sock = new Socket(server_addr, server_port); // 2.获取连接管道的输出流 OutputStream send_stream = send_sock.getOutputStream(); // 3.字节输入流读取本地文件数据,并使用套接字的输出流发送出去 local_read = new FileInputStream("d:/myjava/net/SQL.docx"); byte[] buf = new byte[1024]; int len = 0; while ((len = local_read.read(buf)) != -1) { send_stream.write(buf, 0, len); } // 4.标记输出流到结尾 send_sock.shutdownOutput(); // 5.接收服务端的反馈数据,如上传成功,上传失败等 InputStream recv_stream = send_sock.getInputStream(); BufferedReader ack_recv = new BufferedReader(new InputStreamReader(recv_stream)); String line = null; while ((line = ack_recv.readLine()) != null) { System.out.println(line); } } catch (IOException i) { i.printStackTrace(); } finally { if (send_sock != null) { try { send_sock.close(); local_read.close(); } catch (IOException i1) { i1.printStackTrace(); } } if (local_read != null) { try { local_read.close(); } catch (IOException i2) { i2.printStackTrace(); } } } } }Server端:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class UploadServer { public static void main(String[] args) throws IOException { ServerSocket listen_sock = new ServerSocket(8888); //监听套接字只需创建一个,因此在任务之外 while (true) { //每建立一个连接,就开启一个线程 Socket conn_sock = listen_sock.accept(); //没有新连接进来时,main主线程阻塞在此 new Thread(new Uploader(conn_sock)).start(); } } } class Uploader implements Runnable { private File dest_dir = new File("d:/temp"); // 上传目录 private Socket conn_sock = null; // 连接套接字 InputStream recv_stream = null; FileOutputStream dest_stream = null; Uploader(Socket conn_sock) throws IOException { this.conn_sock = conn_sock; } public void run() { try { if (!dest_dir.exists()) { dest_dir.mkdirs(); } // 1.获取连接管道的输入流 recv_stream = conn_sock.getInputStream(); // 客户端ip String client_ip = conn_sock.getInetAddress().getHostAddress(); System.out.println(client_ip + ".....connected"); // 2.文件的上传位置,即输出目标,以ip命名。如果文件已存在,则使用括号加数字新建文件,如"192.168.100.23(1).txt" File dest_file = new File(dest_dir, client_ip + ".docx"); int count = 1; while (dest_file.exists()) { dest_file = new File(dest_dir, client_ip + "(" + count + ")" + ".docx"); count++; } // 3.读取数据并写入目标文件 dest_stream = new FileOutputStream(dest_file); byte[] buf = new byte[1024]; int len = 0; while ((len = recv_stream.read(buf)) != -1) { dest_stream.write(buf, 0, len); } // 4. 向客户端反馈信息 OutputStream ack_send = conn_sock.getOutputStream(); byte[] text = "upload successful!".getBytes(); ack_send.write(text); } catch (IOException e1) { e1.printStackTrace(); } finally { if (dest_stream != null) { try { dest_stream.close(); } catch (IOException i) { i.printStackTrace(); } } if (conn_sock != null) { try { conn_sock.close(); } catch (IOException i) { i.printStackTrace(); } } } } }