服务器端:
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.logging.Logger; public class TCPEchoServerExecutor { public static void main(String[] args) throws IOException { if (args.length != 1) throw new IllegalArgumentException("Parameter(s):<Port>"); int echoServPort = Integer.parseInt(args[0]); final ServerSocket servSock = new ServerSocket(echoServPort); Logger logger = Logger.getLogger("practical"); Executor servExecutor = Executors.newCachedThreadPool(); while (true) { Socket clntSock = servSock.accept(); servExecutor.execute(new CompressProtocol(clntSock, logger)); } } }
压缩文件:
import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.GZIPOutputStream; /** * 使用GZIP算法实现服务器端的压缩协议,服务器端从客户端接收未压缩的字节,并将其写入GZIPOutputStream * */ public class CompressProtocol implements Runnable { public static final int BUFSIZE = 1024; private Socket clnSock; private Logger logger; public CompressProtocol(Socket clnSock, Logger logger) { this.clnSock = clnSock; this.logger = logger; } public static void handleCompressClient(Socket clnSock, Logger logger) { try { // 从套接字中得到输入输出流 InputStream in = clnSock.getInputStream(); GZIPOutputStream out = new GZIPOutputStream(clnSock .getOutputStream()); byte[] buffer = new byte[BUFSIZE];// 分配读/写缓存 int bytesRead; while ((bytesRead = in.read(buffer)) != -1) out.write(buffer, 0, bytesRead); out.finish(); logger.info("Client " + clnSock.getRemoteSocketAddress() + " finished"); } catch (IOException ex) { logger.log(Level.WARNING, "Exception in echo protocol", ex); } try { clnSock.close(); } catch (IOException e) { logger.info("Exception = " + e.getMessage()); } } public void run() { handleCompressClient(this.clnSock, this.logger); } }
客服端上传接收文件:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /** * 从指定文件读取为压缩字节,上传给服务器压缩,并将从服务器读取压缩后的字节写入一个新的文件。程序仅仅适合于处理小文件,过大会出现死锁 */ public class CompressClient { public static final int BUFSIZE = 256;// 缓冲区大小 public static void main(String[] args) throws IOException { if (args.length != 3) throw new IllegalArgumentException(// 验证参数 "Parameter(s):<Server> <Port> <File>"); String server = args[0];// 服务器名或IP地址 int port = Integer.parseInt(args[1]);// 端口号 String filename = args[2];// 需要压缩的文件 final FileInputStream fileIn = new FileInputStream(filename); FileOutputStream fileOut = new FileOutputStream(filename + ".gz"); final Socket sock = new Socket(server, port); // 发送未压缩的byte流给服务器,未防止死锁的出现,可以将sendBytes(sock,fileIn)方式放入一个线程中 // sendBytes(sock, fileIn); Thread thread = new Thread() { @Override public void run() { try { sendBytes(sock, fileIn); } catch (IOException e) { } } }; thread.start(); // 接收服务器传回的压缩后的byte流 InputStream sockIn = sock.getInputStream(); int bytesRead; // 每次读取的bytes数量 byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = sockIn.read(buffer)) != -1) { fileOut.write(buffer, 0, bytesRead); System.out.print("R");// 读进度指示标识 } System.out.println(); sock.close(); fileIn.close(); fileOut.close(); } /** * 从文件中读取所有未压缩的字节,并将其写入套接字(Socket)的输入流 */ private static void sendBytes(Socket sock, FileInputStream fileIn) throws IOException { OutputStream sockOut = sock.getOutputStream(); int bytesRead; byte[] buffer = new byte[BUFSIZE]; while ((bytesRead = fileIn.read(buffer)) != -1) { sockOut.write(buffer, 0, bytesRead); System.out.print("W");// 写进度指示标识 } sock.shutdownOutput();// 结束发送 } }
