两个服务器提供文件共享服务。 1. 服务器A和服务器B提供文件上传下载服务。服务器A是主服务器,服务器B是备用服务器。 
2. 有5个客户端同时上传不同的大文件(200M~500M),当上传开始1分钟后随意启动N个客户端(命令行输入),每个客户端在这5个上传中的文件中随机选择一个文件下载 
3. 中间突然停掉服务器A并保持服务器B继续服务 整个过程能顺利进行,所有下载的文件是完整并且正确的。请用Java编写,不用写界面。 请高手给点思路,thankyou。

解决方案 »

  1.   

    利用协议或者socket可能实现吧
      

  2.   

    1. 服务器A和服务器B提供文件上传下载服务。服务器A是主服务器,服务器B是备用服务器客户端如果是网络分布,那么你需要采用分布式来做,说白了就是一个服务器核心服务器提供任务部署,第二个服务器是为了防止意外情况的备用服务器。2. 有5个客户端同时上传不同的大文件(200M~500M),当上传开始1分钟后随意启动N个客户端(命令行输入),每个客户端在这5个上传中的文件中随机选择一个文件下载这里你用线程异步来做,主要是处理I/O的并发任务,也没什么。3. 中间突然停掉服务器A并保持服务器B继续服务  主服务器出现异常,那么需要将主服务器的数据拷贝到备用服务器上,当然主服务器处理任务的时候需要备份副本,出现异常也就自动移动到备用服务器继续服务。
      

  3.   


    package com.huawei.test;import java.rmi.Remote;
    import java.rmi.RemoteException;/**
     * 远程接口定义 
     */
    public interface RemoteMethod extends Remote
    {
    /**
     * 远程文件上传
     *
     * @param String : 文件磁盘路径
     * @throws RemoteException
     *  @return void
     */
    public String sendUp(String filePath) throws RemoteException;
    }package com.huawei.test;import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;/**
     * 远程核心服务器端 
     *
     * 启动远程服务,注册远程对象
     */
    public class TaskServerA 
    {
    /* 远程接口实现类 */
    private RemoteMethodImp remoteMethodImp;

    public TaskServerA(String pathFile)
    {
    try 
    {
    //new Thread(remoteMethodImp = new RemoteMethodImp(pathFile)).start();
    remoteMethodImp = new RemoteMethodImp(pathFile);
    }
    catch (RemoteException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;
    }

    /* 启动远程服务 */
    serverStart();
    }

    /**
     * 远程服务器启动远程对象绑定 
     *
     * @exception RemoteException, RemoteException, 
     * MalformedURLException
     * @return void
     */
    public void serverStart()
    {
    /* 远程服务端口 */
    try 
    {
    LocateRegistry.createRegistry(8888);
    }
    catch (RemoteException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;
    }

    /* 注册远程对象 */
    try 
    {
    final String KIDNAPPER = "rmi://191.169.50.199:8888//remoteMethodImp";
    Naming.rebind(KIDNAPPER, remoteMethodImp);
    System.out.println("远程核心服务器启动...");
    }
    catch (RemoteException e) 
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;

    catch (MalformedURLException e) 
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;
    }
    }

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
    TaskServerAFactory.getTaskServerA();

    }
    }/**
     * 核心服务器工厂类
     */
    class TaskServerAFactory
    {
    public static TaskServerA getTaskServerA()
    {
    /* 测试客户端上传文件 */
    final String filePath = "F:/value.txt";
    return new TaskServerA(filePath);
    }
    }未完待续,今天没时间了,要开会。
      

  4.   

    同步 socket 应该可以实现了。
      

  5.   

    写了个简单的,也没写完,用socket和IO写的import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;public class Server {
    private ServerSocket serverSocket = null;
    private Socket socket = null; public void getFile(int port) {
    try {
    serverSocket = new ServerSocket(port);
    System.out.println("server start....");
    while (true) {
    socket = serverSocket.accept(); System.out.println(socket.getInetAddress()
    + " is connected the server..."); Thread serverThread = new ServerThread(socket);
    serverThread.start();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    } class ServerThread extends Thread {
    private Socket socket; public ServerThread(Socket socket) {
    this.socket = socket;
    } public void run() {
    File file = null; DataInputStream in = null;
    DataOutputStream out = null; try {
    in = new DataInputStream(socket.getInputStream());
    out = new DataOutputStream(socket.getOutputStream());
    if (in.readChar() == '?') {
    downloadFile(in, out, file);
    } else {
    uploadFile(in, out, file);
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (in != null)
    in.close();
    if (out != null)
    out.close();
    if(socket!=null){
    socket.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    } public void uploadFile(DataInputStream in, DataOutputStream out,
    File file) {
    try {
    String fileName = null;
    StringBuffer stringBuffer = new StringBuffer();
    char c = '\\';
    while ((c = in.readChar()) != '\\') {
    stringBuffer.append(c);
    }
    fileName=stringBuffer.toString().substring(0, stringBuffer.length());
    file = new File("e:\\back\\" + fileName);

    long pointer=in.readLong();
    out.writeLong(file.length());

    if(file.length()==0){
    out.write(-1);
    }else if(file.length()-pointer > -1){
    in = new DataInputStream(new FileInputStream(file));

    int i = -1;
    byte[] buffer = new byte[1024*512];
    while ((i = in.read(buffer)) != -1) {
    out.write(buffer, 0, i);
    pointer+=i;
    }
    out.write(-1);
    }else{
    out.write(-1);
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (in != null)
    in.close();
    if (out != null)
    out.close();
    if(socket!=null){
    socket.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    } } public void downloadFile(DataInputStream in, DataOutputStream out,
    File file) {
    try {
    String fileName = null;
    StringBuffer stringBuffer = new StringBuffer();
    char c = '\\';
    while ((c = in.readChar()) != '\\') {
    stringBuffer.append(c);
    }
    fileName = socket.getInetAddress() + "-"
    + stringBuffer.toString();
    file = new File("e:\\back\\" + fileName); out.writeLong(file.length()); out = new DataOutputStream(new FileOutputStream(file, true)); int i = -1;
    byte[] buffer = new byte[1024];
    while ((i = in.read(buffer)) != -1) {
    out.write(buffer, 0, i);
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (in != null)
    in.close();
    if (out != null)
    out.close();
    if(socket!=null){
    socket.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
      

  6.   

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.Properties;public class Client extends Thread {
    private Properties props = new Properties();
    private String serverIP;
    private int serverPort;
    private String backupIP;
    private int backupPort;
    private Socket socket;

    public Properties getProps() {
    return props;
    } public void setProps(Properties props) {
    this.props = props;
    } public String getServerIP() {
    return serverIP;
    } public int getServerPort() {
    return serverPort;
    } public String getBackupIP() {
    return backupIP;
    } public int getBackupPort() {
    return backupPort;
    } public Client() {
    props.setProperty("serverIP", "localhost");
    props.setProperty("serverPort", "9999");
    props.setProperty("backupIP", "localhost");
    props.setProperty("backupPort", "8989"); this.serverIP = "localhost";
    this.serverPort = 9999;
    this.backupIP = "localhost";
    this.backupPort = 8989;
    } public void upLoad(String filePath,String IP,int port) {
    long pointer = 0;
    File file = new File(filePath); DataInputStream in = null;
    DataOutputStream out = null;

    try {
    socket=getSocket(IP, port);

    in = new DataInputStream(socket.getInputStream());
    out = new DataOutputStream(socket.getOutputStream()); // 发送文件名
    out.writeChars("?" + file.getName() + "\\"); // 得到指针
    pointer = in.readLong();
    System.out.println("pointer==" + pointer);
    if (file.length() - pointer > -1) {

    System.out.println("开始上传...");
    in = new DataInputStream(
    new FileInputStream(new File(filePath)));

    in.skip(pointer);

    int i = -1;
    byte[] buffer = new byte[1024*512];
    while ((i = in.read(buffer)) != -1) {
    sleep(100);
    out.write(buffer, 0, i);
    pointer += i;
    }
    out.write(-1);
    }
    System.out.println("上传完毕");

    } catch (SocketException e) {
    if (socket.getPort()==this.serverPort) {
    try {
    if (in != null)
    in.close();
    if (out != null)
    out.close();
    if (socket != null)
    socket.close();
    System.out.println("切换服务器...");
    upLoad(filePath,this.backupIP,this.backupPort);
    } catch (IOException e1) {
    e.printStackTrace();
    }
    } else {
    e.printStackTrace();
    }
    } catch (UnknownHostException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (InterruptedException e) {
    e.printStackTrace();
    } finally {
    try {
    if (in != null)
    in.close();
    if (out != null)
    out.close();
    if (socket != null)
    socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    } }
    } public void download(String filePath,String fileName,String IP,int port) {
    File file = new File(filePath+fileName);
    System.out.println("filelength==="+file.length());
    if(file.length()<1){
    File tempFile = new File(filePath+fileName+".tmp");
    System.out.println("tempFilelength===="+tempFile.length());
    long fileSize=0;
    DataInputStream in = null;
    DataOutputStream out = null;

    try {
    socket=getSocket(IP, port);

    in = new DataInputStream(socket.getInputStream());
    out = new DataOutputStream(socket.getOutputStream());


    out.writeChars(" "+fileName+"\\");
    out.writeLong(tempFile.length());

    fileSize=in.readLong();
    System.out.println("filesize===="+fileSize);

    out = new DataOutputStream(new FileOutputStream(tempFile, true)); int i = -1;
    byte[] buffer = new byte[1024 * 512];
    while ((i = in.read(buffer)) != -1) {
    out.write(buffer, 0, i);
    }
    System.out.println(tempFile.length()-fileSize);

    } catch (UnknownHostException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if(tempFile.length()==fileSize){

    }
    try {
    if (in != null)
    in.close();
    if (out != null)
    out.close();
    if(tempFile.length()-fileSize > -1)
    renameFile(tempFile, filePath,fileName,0);
    if (socket != null)
    socket.close();

    } catch (IOException e) {
    e.printStackTrace();
    } }
    }
    }



    public boolean renameFile(File tempFile,String filePath,String fileName,Integer i) throws IOException{
    File file =null;
    if(i==0){
    file = new File(filePath+fileName);
    }else{
    file = new File(filePath+i+"-"+fileName);
    }
    if(tempFile.renameTo(file)){
    return true;
    }
    if(i<255){
    return renameFile(tempFile, filePath, fileName, i+1);
    }
    return false;
    }

    @SuppressWarnings("finally")
    public Socket getSocket(String IP,int port) throws UnknownHostException, IOException{
    if(this.socket!=null){
    System.out.println(this.socket.getInetAddress()+":"+(IP)+"===:==="+ (this.socket.getPort()+":"+port));
    if(this.socket.getInetAddress().equals(IP)&& this.socket.getPort()==port){
    return this.socket;
    }else{
    return new Socket(IP,port);
    }
    }else{
    return new Socket(IP,port);
    }
    } public static void main(String[] args) {
    Client client = new Client();
    //client.upLoad("e:\\a.jpg",client.getServerIP(), client.getServerPort());
    client.download("e:\\back\\download\\","127.0.0.1-a.jpg",client.getServerIP(), client.getServerPort());
    }
    }
      

  7.   

    用JAVA写热备份???
    很有创意的想法
    第一印象觉得很不可思议;
    仔细想想光从热备的要求上来说,上传的时候备份服务器同步处理信息应该可以!
    再想想,不对,A都挂了,客户端怎么知道B是来接班的?
    IP漂移,那就不是JAVA能干的事
    就算JAVA能干,进行中的事务不可能完美过渡
    你的文件假设在A机上传/下载了10个包,同时这些动作同步映射到B服务器;
    这些过程中,客户端只联系A,而不管B,B上的信息是由A主动让B进行同步;
    当A处理到第11个包的时候,挂了,却没有把第11个包的内容发送给B,而客户端的确是把包已经发送出去了,A也告诉它收到了,这时候你让B从哪里变出第11个包?
    也许可以让服务器对数据进行颗粒化处理,颗粒有序编号,每个服务器都标明自己当前事务的处理进度,当B接管的时候回应客户端“你发给我的是12,我连11都还没有呢,从11开始”
    还有很多想法,说不完了,高可用性不是纯粹用代码写出来的!!!
      

  8.   

    像你这种情况,如果不是高度要求的服务;
    你只要做到服务器确定你完成了整个上传下载过程的时候,正确告诉客户端,同时客户端再来个反馈,像TCP/IP的三次握手那样;
    另外,一定要着重确保,服务器不保存发生错误的数据;
    也就是保证事务是完整的,而不保证事务总是被执行;
    即使现在数据库这么牛X的年代,一个SQL执行一半,机器挂了,也没那个厂商的数据库服务器能做到这个SQL非得给我执行完不可!!!
      

  9.   

    只是个面试题,楼上没必要那么叫真,我们写的只是思路并不是最终实现,不要开口闭口就是java怎么怎么不能做到,怎么怎么效率低影响服务器整体性能,你最后既然都说数据库那么牛X的年代,那么请问你现在oracle是用什么写的?自己不能写出来不代表java不能做,半行代码都没拿来佐证,一套套的说辞想必不能服众哦
      

  10.   

    我哪里"开口闭口就是java怎么怎么不能做到,怎么怎么效率低影响服务器整体性能"了?
    知道你写的代码多,不跟你抢分!
    我从头到尾都只是简单的陈诉自己的思考过程,你这么激动干嘛!
    ORACLE我是写不出来,我就不问下一句了,免得多事!
      

  11.   

    并不是和你激动什么,只不过很多问题都是慢慢想就想明白的,这里并没有说客户端的上传和下载是通过什么方式,我们就可以认为客户端的上传下载是通过我们写的客户端程序
    A和B的同步确实无法做到100%保证,正如你所说的我们可以在A接受到数据的时候写入A本地的文件,同时发送输出给B,但是可能A正好接受到一半的数据,也就是代码执行到发送给B的时候A挂掉,数据就产生了不同步但是数据的完整性还是可以确保的,文件都是有长度的,客户端在A挂掉之后会捕获到一个SocketException
    这时候客户端去和B建立socket,然后先发送本地文件长度,B接收到之后判断B的本地文件长度发送回客户端
    客户端通过判断如果B的文件长度小于客户端本地的文件长度,就把B的文件长度作为指针开始读取本地文件输出给B,这样就不会出现数据错误了,A和B的服务器其实启动的时候并不能直接启动服务,而是启动服务器之间的文件同步操作,一旦同步完成才开始启动针对客户端的服务,下载同理最后驳一句,高性能还真就是代码写出来的,要是没有代码的话,执行
    long j=2;
    for(long i =2;i<10000000;i++){
        j=i*j;
    }
    代码效率高了很多,要是用纸和比,要算多久哦-。-
      

  12.   

    楼上争论的确是有点激烈,但是有个问题,JavaI/O的传输效率是很低下的,需要借助第三方工具包
      

  13.   


    楼主我认识的,只是探讨思路,我觉得提出自己的思路或者提出问题比较有意义,这里本来就是个面试题,并不是实际实现,面试题给出的环境就是要求用java,我们也没办法啊,java的执行效率自然比不上c++这是先天决定的,没办法,目前还没有编译器能够让编译出来的java速度和c++一样另外就是你说的问题,IO传输效率低下,需要借助第三方工具包,我不太明白,能说下是什么工具包么?
    java本身来说IO是比较底层的输入输出方式了,单纯的说效率其实和c++比倒没有真的差距那么大,关键还是看IO的次数,
      

  14.   

    确实不错,我已和qjtttt在这个问题上了解了很多,自己没有什么思路。
    不过我想在此问一下,可不可以在上传到a服务器的时候,将b服务器实现同步复制呢。
      

  15.   

    不争了,一个面试题讨论可用性真么没意义,焦点换下,还是换在思路上吧,其实你最早的帖子里面有些地方说的还是有点意思的,我们焦点偏了,重新讨论。
    可以实现伪同步,完全同步不太现实,上面我说了,如果A执行到同步给B的时候正好挂掉的话,A的数据就比B要多,伪同步的实现方法蛮多了,最简单的就是A在接收到客户端发送过来的数据包的时候应该执行输出到文件,这时候只要多加一句把A接收到从客户端哪里接收到的数据包原封不动的给B就可以了
    但是要是深入点想的话就影响效率了,因为这时候客户会发下一个发送数据过来,但是A要先传输给B完成后才能再接收,这样的话客户就需要等待了,这里如果要提高效率就得启动新线程用来输出给B,但是要记得同步控制否则的话是异步的,可能会出现后面的包写在前面的包之前
      

  16.   

    高手好多啊,有时间常来,一来可以学到更多的JAVA知识,二来也可以看看JAVA高手们是怎么竞争和怎么争的……好像斗鸡…………好好一道题,帮忙解决下不就没事了??争论的时间还可以看看其他的贴子嘞…………哎…………悲哀………………
      

  17.   

    up  先不结  看看还有没有gr