服务器端采用多线程方式并行处理传输请求以提高效率。
因为我想用JavaServiceWrapper将 程序作为windows服务运行,所以main方法中需接收一些参数,比如端口、密钥文件位置、文件存放路径等。
1.从main方法接受配置参数
for(String arg : args){ String argName = arg.substring(0,arg.indexOf(":")).trim(); String argValue = arg.substring(arg.indexOf(":")+1).trim(); if(argName.equals("rsa_private")){ privateKey = argValue; }else if(argName.equals("rsa_public")){ publicKey = argValue; }else if(argName.equals("port")){ port = Integer.parseInt(argValue); }else if(argName.equals("file_dir")){ file_dir = argValue; } }
2.初始化解密、签名类实例
RSASecurityCoder coder = new RSASecurityCoder(privateKey); RSASecuritySignature sign = new RSASecuritySignature(publicKey);
3.建立服务器
private static void runServer(String[] args){ long start = System.currentTimeMillis(); //获取配置参数 for(String arg : args){ String argName = arg.substring(0,arg.indexOf(":")).trim(); String argValue = arg.substring(arg.indexOf(":")+1).trim(); if(argName.equals("rsa_private")){ privateKey = argValue; }else if(argName.equals("rsa_public")){ publicKey = argValue; }else if(argName.equals("port")){ port = Integer.parseInt(argValue); }else if(argName.equals("file_dir")){ file_dir = argValue; } } //配置 coder = new RSASecurityCoder(privateKey); sign = new RSASecuritySignature(publicKey); //启动服务器 System.out.println("服务器启动中..."); try { ss = new ServerSocket(port); clientCount = 0; } catch (NumberFormatException e) { System.err.println("端口配置错误"); } catch (IOException e) { System.err.println("服务器在端口"+port+"启动失败"); } //文件存放目录 dir = new File(file_dir); if(!dir.exists()){ dir.mkdir(); } System.out.println("服务器已启动,端口: "+port); //计算启动时间 long end = System.currentTimeMillis(); System.out.println("共消耗 "+(end-start)+" ms."); //接收数据 while(true){ try { if(ss == null){ ss = new ServerSocket(port); clientCount = 0; } Socket socket = ss.accept(); clientCount += 1; System.out.println("有新的连接,当前总连接数:"+clientCount); Thread th = new Thread(new ServerProcessor(socket)); th.start(); } catch (IOException e) { e.printStackTrace(); } } }
3.建立线程类ServerProcessor处理每个文件
static class ServerProcessor extends Thread{ private Socket socket; private InputStream in; private String filename; private long totalBytes; private File file; private FileOutputStream fos; public ServerProcessor(Socket socket){ this.socket = socket; } @Override public void run(){ try { in = socket.getInputStream(); DataInputStream dis = new DataInputStream(in); filename = dis.readUTF(); //读取文件名 totalBytes = dis.readLong(); //读取文件大小 file = new File(dir,filename); fos = new FileOutputStream(file); //FileOutputStream fos = new FileOutputStream(File.createTempFile(filename, null, dir)); //输出日志 //RSA加密以128 bytes位单位,一次最多加密117bytes. byte[] buf = new byte[128]; int available; while((available = in.read(buf)) != -1){ //读取签名 byte[] signature = buf; //读取数据 buf = new byte[128]; available = in.read(buf); byte[] availableBytes = null; if(available == buf.length){ availableBytes = buf; }else{ availableBytes = new byte[available]; for (int i = 0; i < available; i++) { availableBytes[i] = (Byte) buf[i]; } } //验证数据签名 boolean flag = sign.verifySignature(availableBytes, signature); //写入数据 if(flag){ //count += availableBytes.length; fos.write(coder.decrypt(availableBytes)); //System.out.println(""+count+" bytes received"); } } fos.close(); socket.shutdownInput(); clientCount -= 1; System.out.println("有连接断开,当前总连接数:"+clientCount); System.out.println(new SimpleDateFormat("[yyyy-MM-DD HH:mm:ss ]").format(new Date()) +filename+" 接收完毕. 大小 "+(totalBytes/1024)+" kb,保存路径:"+dir.getAbsolutePath()); } catch (NumberFormatException e) { System.err.println("端口配置错误"); e.printStackTrace(); } catch (FileNotFoundException e) { System.err.println("文件没找到,文件名:"+filename+",可能是因为读取socket数据失败"); e.printStackTrace(); } catch (IOException e) { System.err.println("文件读/写错误"); try { fos.close(); } catch (IOException e1) { e1.printStackTrace(); } file.delete(); e.printStackTrace(); } } }
main方法
public static void main(String[] args) { runServer(args); }
本文介绍了一个使用Java实现的服务端应用,该应用通过多线程方式处理客户端的文件传输请求,并采用RSA加密技术确保数据的安全性。服务端能够接收带有端口、密钥文件位置等配置参数的main方法输入。
1111

被折叠的 条评论
为什么被折叠?



