Java TCP文件传输数据随机丢失

Java TCP文件传输数据随机丢失,java,file,tcp,Java,File,Tcp,[编辑:这篇文章被标记为重复,但没有进行适当的审阅。这两篇文章解决了完全不同的问题,审阅者没有花时间仔细阅读。] 服务器将连接到客户端的三个实例。服务器有三个线程来接收来自这三个客户端的请求。客户端的三个实例中的每一个都有一个ServerThread(服务器从该线程请求文件或文件列表)和一个UserThread(它将接受用户输入并与服务器通信,并根据用户输入接收文件/文件列表) 假设客户机_0需要一个由客户机_1拥有的文件。当client_0的UserThread向服务器请求文件时,服务器与cl

[编辑:这篇文章被标记为重复,但没有进行适当的审阅。这两篇文章解决了完全不同的问题,审阅者没有花时间仔细阅读。]

服务器将连接到客户端的三个实例。服务器有三个线程来接收来自这三个客户端的请求。客户端的三个实例中的每一个都有一个ServerThread(服务器从该线程请求文件或文件列表)和一个UserThread(它将接受用户输入并与服务器通信,并根据用户输入接收文件/文件列表)

假设客户机_0需要一个由客户机_1拥有的文件。当client_0的UserThread向服务器请求文件时,服务器与client_1的ServerThread通信,client_1的ServerThread向服务器发送文件的
byteArray
。然后服务器将
byteArray
发送回客户端0的用户线程,客户端0然后将
byteArray
保存为文件

我使用相同类型的代码,服务器从客户端1接收
bytearray
,客户端0从服务器接收
bytearray
。服务器的代码每次都能完美地工作,并能完美地接收
byteArray
,但在客户端0中,接收
byteArray
的循环卡在文件的最后一部分,尽管同一类型的循环在服务器中工作得很好。变量
position
保存已接收的
byteArray
的数量,并且它在客户端0中未达到
文件大小,但在服务器中这样做没有任何问题。
System.out.println()语句证实了这一点

此外,客户端0中的此问题90%的时间都在发生。在另外10%的情况下,客户端0中的循环与预期的一样工作!为什么会这样

代码很长,但如果有人能够通过并给出一些建议,这将是一个很大的帮助

服务器:

package server;
import java.io.*;
import java.net.*;

public class Server {

    public static void main(String[] args) throws Exception {
        String[] id={"cp 1","cp 2","cp 3"}, pass={"123","456","789"};
        ServerSocket welcome = new ServerSocket(6000), tmpSocket;
        Socket STsocket, UTsocket;
        int startSTport = 6001;
        int startUTport = 6011;

        // for ServerThread of client
        BufferedReader STmsgFrom[] = new BufferedReader[3];
        PrintWriter STmsgTo[] = new PrintWriter[3];
        DataInputStream[] STfileFrom = new DataInputStream[3];
        // for UserThread of client
        BufferedReader UTmsgFrom[] = new BufferedReader[3];
        PrintWriter UTmsgTo[] = new PrintWriter[3];
        DataOutputStream[] UTfileTo = new DataOutputStream[3];

        for(int i=0; i<3; i++) {
            // connecting initially
            System.out.println("Waiting for client "+i);
            Socket client = welcome.accept();
            PrintWriter send = new PrintWriter(client.getOutputStream(),true);
            BufferedReader receive = new BufferedReader(new InputStreamReader(client.getInputStream()));

            // sending serial number
            send.println(Integer.toString(i));

            // sending ports for thread sockets
            send.println(Integer.toString(startSTport+i));
            send.println(Integer.toString(startUTport+i));

            // accepting sockets
            tmpSocket = new ServerSocket(startSTport+i);
            STsocket = tmpSocket.accept();
            tmpSocket = new ServerSocket(startUTport+i);
            UTsocket = tmpSocket.accept();

            // creating communications
            STmsgFrom[i] = new BufferedReader(new InputStreamReader(STsocket.getInputStream()));
            STmsgTo[i] = new PrintWriter(STsocket.getOutputStream(),true);
            STfileFrom[i] = new DataInputStream(STsocket.getInputStream());

            UTmsgFrom[i] = new BufferedReader(new InputStreamReader(UTsocket.getInputStream()));
            UTmsgTo[i] = new PrintWriter(UTsocket.getOutputStream(),true);
            UTfileTo[i] = new DataOutputStream(UTsocket.getOutputStream());

            System.out.println("Connected client "+i);
        }

        ClientThread ct0 = new ClientThread(0,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
        ClientThread ct1 = new ClientThread(1,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
        ClientThread ct2 = new ClientThread(2,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
        ct0.start();
        ct1.start();
        ct2.start();

        System.out.println("Server Stup Complete!");
    }

}

class ClientThread extends Thread {
    String msg;
    int cid;
    BufferedReader[] STmsgFrom;
    PrintWriter[] STmsgTo;
    DataInputStream[] STfileFrom;

    BufferedReader[] UTmsgFrom;
    PrintWriter[] UTmsgTo;
    DataOutputStream[] UTfileTo;
    public ClientThread(int cid,BufferedReader[] STmsgFrom,PrintWriter[] STmsgTo,DataInputStream[] STfileFrom,BufferedReader[] UTmsgFrom,PrintWriter[] UTmsgTo,DataOutputStream[] UTfileTo) {
        this.cid=cid;

        this.STmsgFrom=STmsgFrom;
        this.STmsgTo=STmsgTo;
        this.STfileFrom = STfileFrom;

        this.UTmsgFrom=UTmsgFrom;
        this.UTmsgTo=UTmsgTo;
        this.UTfileTo = UTfileTo;
    }

    @Override
    public void run() {
        while(true) {
            try {
               // receiving request from receiver UserThread
                msg = UTmsgFrom[cid].readLine();
                if(msg.equals("get list")) {    // receiver requested for file list
                    System.out.println("Request from "+cid+": "+msg);
                    for(int i=0; i<3; i++) {
                        if(i==cid) continue;

                        // sending request to sender ServerThread
                        STmsgTo[i].println("give list");
                        System.out.println("Request to "+i);

                        // receive file count from sender ServerThread
                        int cnt = Integer.parseInt(STmsgFrom[i].readLine());
                        System.out.println(i+" has files: "+cnt);

                        // sending source identity to receiver UserThread
                        UTmsgTo[cid].println(Integer.toString(i));

                        // send file count back to receiver UserThread
                        UTmsgTo[cid].println(Integer.toString(cnt));

                        // get and send file names to receiver
                        for(int j=0; j<cnt; j++) {
                            msg = STmsgFrom[i].readLine();
                            UTmsgTo[cid].println(msg);
                        }
                    }
                } else if(msg.equals("get file")) {
                    // get source id and filename
                    int source = Integer.parseInt(UTmsgFrom[cid].readLine());
                    String fileName = UTmsgFrom[cid].readLine();
                    //System.out.println("get source id and filename");

                    // ask source about file
                    STmsgTo[source].println("give file");
                    STmsgTo[source].println(fileName);
                    boolean fileOk = Boolean.parseBoolean(STmsgFrom[source].readLine());
                    //System.out.println("ask source about file");

                    // telling receiver about file status
                    UTmsgTo[cid].println(Boolean.toString(fileOk));
                    //System.out.println("telling receiver about file");

                    if(fileOk) {
                        // get copy request from receiver
                        msg = UTmsgFrom[cid].readLine();
                        //System.out.println("receiver copy command");
                        if(msg.equals("yes copy")) {
                            System.out.println("Copying \'"+fileName+"\' from "+source+" to "+cid);
                            // tell sender to copy
                            STmsgTo[source].println("yes copy");
                            //System.out.println("tell sender copy command");

                            // copy from SENDER
                            // get file size
                            int FILE_SIZE = Integer.parseInt(STmsgFrom[source].readLine());
                            byte[] fileBytes = new byte[FILE_SIZE];
                            System.out.println("Get file size "+FILE_SIZE);
                            // get file data
                            int portion = STfileFrom[source].read(fileBytes,0,fileBytes.length);
                            int position = portion;
                            do {
                                portion = STfileFrom[source].read(fileBytes,position,fileBytes.length-position);
                                if(portion>=0) {
                                    position += portion;
                                }
                                System.out.println("position = "+position);
                            } while(position<FILE_SIZE);
                            System.out.println("Get file data "+position);

                            // copy to RECEIVER
                            // send file size
                            UTmsgTo[cid].println(Integer.toString(FILE_SIZE));
                            //System.out.println("send file size");
                            // send file data
                            UTfileTo[cid].write(fileBytes,0,position);
                            UTfileTo[cid].flush();
                            //System.out.println("send file data");
                            System.out.println("Copying \'"+fileName+"\' complete");
                        } else {
                            // tell sender to ignore copy process
                            STmsgTo[source].println("no copy");
                        }
                    }
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
包服务器;
导入java.io.*;
导入java.net。*;
公共类服务器{
公共静态void main(字符串[]args)引发异常{
字符串[]id={“CP1”、“CP2”、“CP3”},pass={“123”、“456”、“789”};
ServerSocket welcome=新的ServerSocket(6000),tmpSocket;
插座STsocket,UTsocket;
int startSTport=6001;
int startUTport=6011;
//用于客户端的服务器线程
BufferedReader STmsgFrom[]=新的BufferedReader[3];
PrintWriter STmsgTo[]=新的PrintWriter[3];
DataInputStream[]STfileFrom=新DataInputStream[3];
//用于客户端的用户线程
BufferedReader UTmsgFrom[]=新BufferedReader[3];
PrintWriter UTmsgTo[]=新的PrintWriter[3];
DataOutputStream[]UTfileTo=新DataOutputStream[3];
对于(int i=0;iServerSocket.accept()是阻塞的,您不能从同一线程调用它两次


每个ServerSocket都必须在自己的线程中运行。

@EJP-这个问题是如何重复的?您是否在这里花时间阅读了这个问题?
package client;
import java.io.*;
import java.net.*;

public class Client {

    public static void main(String[] args) throws Exception {
        String msg;
        InetAddress inetAddress = InetAddress.getLocalHost();
        String[] allPaths= {"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_1_folder",
                            "H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_2_folder",
                            "H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_3_folder"};

        // connecting to welcome socket
        Socket server = new Socket(inetAddress,6000);
        BufferedReader receive = new BufferedReader(new InputStreamReader(server.getInputStream()));
        BufferedReader receiveUser = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter send = new PrintWriter(server.getOutputStream(),true);

        // receiving serial number
        int cid = Integer.parseInt(receive.readLine());

        // receiving port numbers for thread sockets
        int STport = Integer.parseInt(receive.readLine());
        int UTport = Integer.parseInt(receive.readLine());

        // connecting sockets
        Socket STsocket = new Socket(inetAddress,STport);
        Socket UTsocket = new Socket(inetAddress,UTport);

        System.out.println("Connected to the server.\nSerial: "+cid+"\nFolder path: "+allPaths[cid]);

        ServerThread st = new ServerThread(allPaths[cid],STsocket);
        UserThread ut = new UserThread(cid,allPaths[cid],UTsocket);
        st.start();
        ut.start();
    }
}

class UserThread extends Thread {
    int cid;
    String msg,folderPath;
    BufferedReader msgFromServer,fromUser;
    PrintWriter msgToServer;
    // for file
    DataInputStream fileFromServer;
    BufferedOutputStream writeFile;
    public UserThread(int cid,String folderPath,Socket socket) {
        try {
            this.cid = cid;
            this.folderPath = folderPath;
            fromUser = new BufferedReader(new InputStreamReader(System.in));
            msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            msgToServer = new PrintWriter(socket.getOutputStream(),true);
            // for file
            fileFromServer = new DataInputStream(socket.getInputStream());
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        //System.out.println("User Thread Started!");
        while(true) {
            try {
                msg = fromUser.readLine();
                if(msg.equals("get list")) {
                    // sending request to server
                    msgToServer.println("get list");

                    // getting file list from server
                    System.out.println("-------------------------------------------");
                    for(int i=0; i<2; i++) {
                        // getting source id
                        int source = Integer.parseInt(msgFromServer.readLine());
                        System.out.println("Source: "+source);

                        int cnt = Integer.parseInt(msgFromServer.readLine());
                        System.out.println("Files: "+cnt);
                        System.out.println("--------------");

                        for(int j=0; j<cnt; j++) {
                            msg = msgFromServer.readLine();
                            System.out.println(msg);
                        }
                        System.out.println("-------------------------------------------");
                    }
                } else if(msg.equals("get file")) {
                    // GETTING A FILE
                    int source;
                    while(true) {
                        System.out.println("File Source: ");
                        try {
                            source = Integer.parseInt(fromUser.readLine());
                            if(0<=source && source<=2 && source!=cid) {
                                break;
                            } else {
                                System.out.println("Error: File source invalid. Try again.");
                            }
                        } catch(Exception ex) {
                            System.out.println("Error: File source invalid. Try again.");
                        }
                    }

                    System.out.println("File Name: ");
                    String fileName = fromUser.readLine();

                    // send request to server to check file
                    msgToServer.println("get file");
                    msgToServer.println(Integer.toString(source));
                    msgToServer.println(fileName);

                    // receiving file status
                    boolean fileOk = Boolean.parseBoolean(msgFromServer.readLine());
                    if(!fileOk) {
                        System.out.println("Error: File does not exist at source.");
                    } else {
                        System.out.println("File is available!!");
                        System.out.println("Want to copy \'"+fileName+"\'? (y/n)");
                        msg = fromUser.readLine();
                        if(msg.equals("y")||msg.equals("Y")) {
                            // tell server to copy file
                            msgToServer.println("yes copy");

                            // COPY PROCESS
                            // get file size
                            int FILE_SIZE = Integer.parseInt(msgFromServer.readLine());
                            System.out.println("File size: "+FILE_SIZE+" bytes.");
                            byte[] fileBytes = new byte[FILE_SIZE];

                            // get file data
                            int portion = fileFromServer.read(fileBytes,0,fileBytes.length);
                            int position = portion;
                            do {
                                portion = fileFromServer.read(fileBytes,position,fileBytes.length-position);
                                if(portion>=0) {
                                    position += portion;
                                }
                                System.out.println("position = "+position);
                            } while(position<FILE_SIZE);
                            System.out.println("Total "+position+" bytes received.");

                            // write file data
                            File file = new File(folderPath + "\\" + fileName);
                            writeFile = new BufferedOutputStream(new FileOutputStream(file));
                            writeFile.write(fileBytes,0,position);
                            writeFile.flush();
                            writeFile.close();

                            System.out.println("Copying complete.");
                        } else {
                            msgToServer.println("no copy");
                        }
                    }
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

class ServerThread extends Thread {
    String msg,folderPath;
    BufferedReader msgFromServer;
    PrintWriter msgToServer;
    // for file
    DataOutputStream fileToServer;
    BufferedInputStream readFile;
    public ServerThread(String folderPath,Socket socket) {
        try {
            this.folderPath = folderPath;
            msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            msgToServer = new PrintWriter(socket.getOutputStream(),true);
            // for file
            fileToServer = new DataOutputStream(socket.getOutputStream());
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        //System.out.println("Server Thread Started!");
        while(true) {
            try {
                msg = msgFromServer.readLine();
                if(msg.equals("give list")) {
                    //System.out.println("Request from server: "+msg);
                    File folder = new File(folderPath);
                    File[] fileList = folder.listFiles();
                    int cnt = fileList.length;

                    //System.out.println("Files: "+cnt);

                    // give file count back to server
                    msgToServer.println(Integer.toString(cnt));

                    // give file list back to server
                    for(int i=0; i<cnt; i++) {
                        msgToServer.println(fileList[i].getName());
                    }
                } else if(msg.equals("give file")) {
                    // receive file name
                    String fileName = msgFromServer.readLine();

                    // telling server about file status
                    File file = new File(folderPath + "\\" + fileName);
                    boolean fileOk = file.exists();
                    msgToServer.println(Boolean.toString(fileOk));

                    if(fileOk) {
                        // getting copy request
                        msg = msgFromServer.readLine();
                        if(msg.equals("yes copy")) {
                            // COPY PROCESS
                            // send file size
                            int FILE_SIZE = (int)file.length();
                            msgToServer.println(Integer.toString(FILE_SIZE));

                            // read file data
                            readFile = new BufferedInputStream(new FileInputStream(file));
                            byte[] fileBytes = new byte[FILE_SIZE];
                            readFile.read(fileBytes,0,fileBytes.length);
                            readFile.close();

                            // send file data
                            fileToServer.write(fileBytes,0,fileBytes.length);
                            fileToServer.flush();
                        } // otherwise end of conversation
                    }
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}