簡體   English   中英

無法通過簡單的客戶端/服務器程序

[英]Fails at a simple client/server programme

我有一個分布式應用程序,其中客戶端連接到主服務器M詢問可用服務器列表。 M支持3種操作:1)將新服務器添加到列表中,2)從列表中刪除服務器,3)將整個列表提供給客戶端。 到目前為止,我已經在本地計算機上解決了該問題,但是我的客戶端在列表響應后停止了運行。 我在這里做錯了什么? 代碼如下:

// The client code.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class MainDummyClientApp {

public static final int PORT = 1633;
public static final String DOMAIN = "127.0.0.1";
public static final String CMD_LIST = "list";
public static final String CMD_HELLO_IM_SERVER = "hello from server";
public static final String CMD_BYE_FROM_SERVER = "byebye master";

public static void main(String[] args) {
    List<Socket> sockets = new ArrayList<Socket>();
    Scanner scanner = new Scanner(System.in);
    Map<String, Socket> map = new HashMap<String, Socket>();

    for (;;) {
        System.out.print("> ");
        String cmd = scanner.nextLine();
        String[] subs = cmd.split(" ");

        if (subs[0].equals("connect")) {
            // connect <name> <url>
            Socket s = null;
            try {
                s = new Socket(subs[2], PORT);
                String name = subs[1];
                map.put(name, s);
                sockets.add(s);
            } catch (IOException e) {
                e.printStackTrace(System.err);
            }
        } else if (subs[0].equals("list")) {
            // list <name>
            try {
                PrintWriter out = new PrintWriter(
                        map.get(subs[1]).getOutputStream());
                out.println(CMD_LIST);
                out.flush();

                BufferedReader in = null;

                in = new BufferedReader(
                        new InputStreamReader(
                            map.get(subs[1]).getInputStream()
                            )
                        );

                String line;

                while ((line = in.readLine()) != null) {
                    System.out.println(line);
                }

                in.close();
            } catch (Exception e) {
                e.printStackTrace(System.err);
            }
        } else if (subs[0].equals("knock")) {
            // knock <name>
            Socket s = map.get(subs[1]);
            try {
                PrintWriter out = new PrintWriter(s.getOutputStream());
                out.println(CMD_HELLO_IM_SERVER);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace(System.err);
            }
        } else if (subs[0].equals("bye")) {
            // bye <name>
            Socket s = map.get(subs[1]);
            try {
                PrintWriter out = new PrintWriter(s.getOutputStream());
                out.println(CMD_BYE_FROM_SERVER);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace(System.err);
            }
        }
    }
}
// The master server code.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Semaphore;

public class TUMasterServerMain extends Thread {

public static boolean DEBUG = true;
public static final int PORT = 1633;
public static final String CMD_LIST = "list";
public static final String CMD_HELLO_IM_SERVER = "hello from server";
public static final String CMD_BYE_FROM_SERVER = "byebye master";

private static ServerSocket serverSocket;

private static Set<InetAddress> serverSet = new HashSet<InetAddress>();

private static final Semaphore mutex = new Semaphore(1, true);

private Socket client;

public TUMasterServerMain(Socket client) {
    this.client = client;
}

@Override
public void run() {
    BufferedReader br = null;
    PrintWriter pw = null;

    try {
        br = new BufferedReader(new InputStreamReader(client.getInputStream()));
        pw = new PrintWriter(client.getOutputStream(), true);

        if (DEBUG) {
            System.out.println("[DEBUG] Before server loop.");
        }

        for (;;) {
            String cmd = br.readLine();

            if (DEBUG) {
                System.out.println("[DEBUG] Recieved command: " + cmd);
            }

            if (cmd == null) {
                if (DEBUG) {
                    System.out.println("[DEBUG] Server thread returns.");
                }
                br.close();
                pw.close();
                return;
            }

            if (cmd.equals(CMD_LIST)) {
                mutex.acquireUninterruptibly();
                pw.println(CMD_LIST);
                for (InetAddress serverAddress : serverSet) {
                    pw.write(serverAddress.getHostName() + '\n');
                }
                pw.flush();
                mutex.release();

                if (DEBUG) {
                    System.out.println("[DEBUG] Listing all the servers: " +
                            serverSet.size() + " server(s) are up.");
                }
            } else if (cmd.equals(CMD_HELLO_IM_SERVER)) {
                mutex.acquireUninterruptibly();
                InetAddress address = client.getInetAddress();
                serverSet.add(address);
                mutex.release();

                if (DEBUG) {
                    System.out.println("[DEBUG] New server added: " +
                            address.getHostAddress());
                }
            } else if (cmd.equals(CMD_BYE_FROM_SERVER)) {
                mutex.acquireUninterruptibly();
                InetAddress address = client.getInetAddress();
                if (serverSet.remove(address)) {
                    if (DEBUG) {
                        System.out.println("[DEBUG] Server removed: " +
                                address.getHostAddress());
                    }
                }
                mutex.release();
                return;
            } else {
                throw new IllegalStateException("Should never get here!");
            }
        }
    } catch (IOException e) {
        e.printStackTrace(System.err);
    } finally {
        try {
            br.close();
        } catch (IOException e) {

        }
        pw.close();
    }
}

public static void main(String[] args) {
    // DEBUG = false;
    try {
        serverSocket = new ServerSocket(PORT);
    } catch (IOException e) {
        e.printStackTrace(System.err);
        System.exit(-1);
    }

    for (;;) {
        try {
            Socket s = serverSocket.accept();
            new TUMasterServerMain(s).start();
            System.out.println("[SERVER]: Serving " + s.toString());
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
    }
}
}

如果您實際上描述了所觀察到的意外錯誤或行為,則將更容易回答。

就是說,您遇到的一個問題是客戶端代碼中處理“列表”命令的部分中的“ in.close(); ”行。 Socket.getInputStream()的javadoc中所述:

關閉返回的InputStream將關閉關聯的套接字。

因此,在獲得列表一次之后,您將無法使用該套接字做更多的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM