Java TCP服务器无法从多个客户端接收消息 [英] Java TCP server cannot receive message from more than one client

查看:731
本文介绍了Java TCP服务器无法从多个客户端接收消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做最简单的解释。我的Java TCP项目有一个服务器和三个客户端。

I am going for the simplest explanation. My Java TCP project has a server and three clients.

服务器有一个ClientThread。
每个客户端都有一个ServerThread和一个UserThread。

The server has a ClientThread. The clients each has a ServerThread and a UserThread.

工作流程是:

1.客户端的UserThread(比方说, client_0)获取用户输入,然后向服务器发送消息。

2.服务器的ClientThread从client_0捕获消息,并向另一个客户端(例如client_1)的ServerThread发送另一条消息。

3.然后client_1的ServerThread将另一条消息发送回服务器中运行的ClientThread;

The workflow is:
1. The UserThread of a client (say, client_0) gets user input and then sends a message to the server.
2. The ClientThread of the server captures the message from client_0 and sends another message to the ServerThread of a different client (say, client_1).
3. The ServerThread of client_1 then sends back another message to the ClientThread running in the server;

步骤3的消息是没有到达服务器。

The message of step 3 is not reaching the server.

共有3个客户端,比如client_0,client_1和client_2。

最初的想法是,如果client_0请求服务器然后服务器与client_1和client_2通信。这就是为什么行 if(i == cid)继续; 在服务器的for循环中。但是,如果我注释掉这一行,服务器会与client_0进行通信(这在语义上是不必要的),并且不会发生消息传递问题。之后,服务器与client_1进行通信,然后再次出现问题。

There are total 3 clients, say client_0, client_1 and client_2.
The original idea is that if client_0 requests the server then the server communicates with client_1 and client_2. That's why the line if(i==cid) continue; in the for loop in the server. But, if i comment out this line, the server communicates with the client_0 (which is unnecessary semantically) and the messaging problem doesn't happen. After that the server communicates with client_1 and the problem appears again.

服务器可以从发送原始请求的客户端(client_0)的ServerThread接收消息( msgToServer.println(获取列表)) ; )从它的UserThread开始整个过程​​。但是服务器无法从任何其他客户端的ServerThread获取消息,即使它可以向其他客户端发送消息,并且所有客户端程序都是相同的,并且所有ServerThreads和UserThreads都应该起作用。怎么可能呢?

The server can receive message from the ServerThread of the client (client_0) that sent the original request (msgToServer.println("get list");) from it's UserThread to initiate the whole process. But Server cannot get message from any other client's ServerThread even though it can send message to others and all the client programs are identical and all the ServerThreads and UserThreads should work the same eway. How is it even possible?

服务器:

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

public class ServerFTP {

    static String[] id = {"cp 1","cp 2","cp 3"};
    static String[] pass = {"123","456","789"};

    static BufferedReader[] msgFromClient = new BufferedReader[3];
    static PrintWriter[] msgToClient = new PrintWriter[3];
    static InputStream[] fileFromClient = new InputStream[3];
    static OutputStream[] fileToClient = new OutputStream[3];

    public static void main(String[] args) throws Exception {
        ServerSocket welcome = new ServerSocket(6789);

        // connecting the three clients
        for(int i=0; i<3; i++) {
            System.out.println("Waiting for Client "+i);
            Socket clientSocket;
            clientSocket = welcome.accept();

            while(true) {
                System.out.println("Connecting Client "+i);

                BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream(),true);

                // get id pass from client
                String clientId = fromClient.readLine();
                System.out.println(clientId);
                String clientPass = fromClient.readLine();
                System.out.println(clientPass);

                // check id pass and feedback
                if(clientId.equals(id[i]) && clientPass.equals(pass[i])) {
                    toClient.println("ok");

                    msgFromClient[i] = fromClient;
                    msgToClient[i] = toClient;
                    fileFromClient[i] = clientSocket.getInputStream();
                    fileToClient[i] = clientSocket.getOutputStream();

                    break;
                } else {
                    toClient.println("error");
                }
            }

            ClientThread ct = new ClientThread(i);
            ct.start();
            System.out.println("Client "+i+" connected!");
        }

        welcome.close();
    }

}

class ClientThread extends Thread {
    int cid;
    String msg;

    public ClientThread(int client_id) {
        cid = client_id;

        try {
            // telling client it's serial
            ServerFTP.msgToClient[cid].println(Integer.toString(cid));
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void run() {
        while(true) {
            try {
                // get request from receiver
                msg = ServerFTP.msgFromClient[cid].readLine();
                if(msg.equals("get list")) {
                    System.out.println(cid+" "+msg);

                    msg = ServerFTP.msgFromClient[cid].readLine();
                    System.out.println(cid+" "+msg);

                    for(int i=0; i<3; i++) {
                        if(i==cid) continue;

                        // send sender request for file list
                        ServerFTP.msgToClient[i].println("give list");
                        System.out.println("request sent to client "+i);

                        // get file count from sender
                        msg = ServerFTP.msgFromClient[i].readLine();
                        System.out.println("file count caught!!!"); // THIS LINE NEVER EXECUTES
                        System.out.println("File count "+msg);
                    }
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

< br>
System.out.println(文件计数捕获!!!); 永远不会被调用。

客户:

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

public class ClientFTP_1 {

    static String[] allPaths = {   "...path...\\client_1_folder",
                            "...path...\\client_2_folder",
                            "...path...\\client_3_folder"};

    public static void main(String[] args) throws Exception {
        InetAddress inetAddress = InetAddress.getLocalHost();
        Socket server = new Socket(inetAddress,6789);
        int myId;

        // login phase
        BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
        BufferedReader fromServer = new BufferedReader(new InputStreamReader(server.getInputStream()));
        PrintWriter toServer = new PrintWriter(server.getOutputStream(),true);
        InputStream getFile = server.getInputStream();
        OutputStream sendFile = server.getOutputStream();
        while(true) {
            System.out.println("id: ");
            String msg = fromUser.readLine();
            toServer.println(msg);            

            System.out.println("password: ");
            msg = fromUser.readLine();
            toServer.println(msg);

            msg = fromServer.readLine();
            if(msg.equals("ok")) {
                System.out.println("Connection Successful!");
                myId = Integer.parseInt(fromServer.readLine());
                System.out.println("Client serial is: "+myId);
                System.out.println("Folder path is: "+allPaths[myId]);
                break;
            } else {
                System.out.println("Error! Try again please.");
            }
        }

        ServerThread st = new ServerThread(allPaths[myId],fromUser,fromServer,toServer,getFile,sendFile);
        st.start();
        UserThread ut = new UserThread(allPaths[myId],fromUser,fromServer,toServer,getFile,sendFile);
        ut.start();
    }
}

class ServerThread extends Thread {
    String folderPath;
    String msg;
    BufferedReader msgFromServer,msgFromUser;
    PrintWriter msgToServer;
    InputStream fileFromServer;
    OutputStream fileToServer;
    public ServerThread(String path,BufferedReader fromUser,BufferedReader fromServer,PrintWriter toServer,InputStream getFile,OutputStream sendFile) throws Exception {
        folderPath = path;
        msgFromUser = fromUser;
        msgFromServer = fromServer;
        msgToServer = toServer;
        fileFromServer = getFile;
        fileToServer = sendFile;
    }

    @Override
    public void run() {
        System.out.println("Server Thread Started");
        while(true) {
            try {
                // receive request
                msg = msgFromServer.readLine();
                System.out.println("request received from server");
                if(msg.equals("give list")) {
                    // get filenames
                    File folder = new File(folderPath);
                    File[] fileList = folder.listFiles();
                    int cnt = fileList.length;
                    System.out.println("count calculated");

                    // sned file count to server
                    msgToServer.println(Integer.toString(cnt));
                    System.out.println("count sent to server"); // THIS LINE PRINTS
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

class UserThread extends Thread {
    String folderPath;
    String msg;
    BufferedReader msgFromServer,msgFromUser;
    PrintWriter msgToServer;
    InputStream fileFromServer;
    OutputStream fileToServer;
    public UserThread(String path,BufferedReader fromUser,BufferedReader fromServer,PrintWriter toServer,InputStream getFile,OutputStream sendFile) throws Exception {
        folderPath = path;
        msgFromUser = fromUser;
        msgFromServer = fromServer;
        msgToServer = toServer;
        fileFromServer = getFile;
        fileToServer = sendFile;
    }

    @Override
    public void run() {
        System.out.println("USer Thread Started");
        while(true) {
            try {
                // input from user
                msg = msgFromUser.readLine();
                if(msg.equals("get list")) {
                    // send request to server
                    msgToServer.println("get list");
                    msgToServer.println("fahim list");
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

System.out.println(计算发送到服务器); 已打印。这意味着之前的消息发送行没有问题。

The line System.out.println("count sent to server"); is printed. That means the message sending line before that has executed with no problem.

我知道服务器中的登录系统是愚蠢的。但这项工作没问题。在所有客户端连接并登录到服务器之后,上面解释的所有内容都会发生。

I know the login system in the server is stupid. But it is 'ok' for this work. Everything explained above happens after all the clients have connected and logged in to the server.

推荐答案

我想我发现了这个问题。我正在为客户端程序的ServerThread和UserThread使用相同的套接字。因此,当ServerThread尝试响应服务器时,很可能该消息将通过同一套接字转发到正在侦听消息的服务器中的另一个不同的线程(认为消息来自UserThread)。

I think I have found the problem. I was using the same socket for a client program's ServerThread and UserThread. So while the ServerThread is trying to response to the server, most probably the message is going to another different thread in the server that is listening for message (thinking the message comes from UserThread) through the same socket.

这篇关于Java TCP服务器无法从多个客户端接收消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆