Java TCP многопользовательский чат-сервер, имеющий проблемы с подключением клиента к серверу - PullRequest
0 голосов
/ 02 декабря 2011

Я учусь, как реализовать многопользовательский чат-сервер с использованием TCP в Java.Я натолкнулся на пример этого в Интернете, но что-то не так в файле ChatClient.java.В идеале, когда клиент подключается к серверу, он должен предоставить псевдоним, и если этот псевдоним действителен ... сервер возвращает сообщение «ОК», и сеанс чата может начаться.

Однако, похоже, это не работает.После ввода псевдонима я не получаю сообщение «ОК» с сервера и, следовательно, не могу общаться с помощью клиента.

Ссылка на оригинальный учебный веб-сайт находится здесь (это последний пример): http://pguides.net/java/tcp-client-server-chat

Я пытался найти в теме форума эту статью ... но она кажется мертвой,Я был бы очень признателен, если бы кто-нибудь объяснил мне, почему это не сработает.

ChatServer.java:

/* ChatServer.java */
import java.net.ServerSocket;
import java.net.Socket;

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import java.util.Hashtable;

public class ChatServer {
private static int port = 1001; /* port to listen on */

public static void main (String[] args) throws IOException {

    ServerSocket server = null;
    try {
        server = new ServerSocket(port); /* start listening on the port */
    } catch (IOException e) {
        System.err.println("Could not listen on port: " + port);
        System.err.println(e);
        System.exit(1);
    }

    Socket client = null;
    while(true) {
        try {
            client = server.accept();
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.err.println(e);
            System.exit(1);
        }
        /* start a new thread to handle this client */
        Thread t = new Thread(new ClientConn(client));
        t.start();
    }
   }
}

class ChatServerProtocol {
private String nick;
private ClientConn conn;

/* a hash table from user nicks to the corresponding connections */
private static Hashtable<String, ClientConn> nicks = 
    new Hashtable<String, ClientConn>();

private static final String msg_OK = "OK";
private static final String msg_NICK_IN_USE = "NICK IN USE";
private static final String msg_SPECIFY_NICK = "SPECIFY NICK";
private static final String msg_INVALID = "INVALID COMMAND";
private static final String msg_SEND_FAILED = "FAILED TO SEND";

/**
 * Adds a nick to the hash table 
 * returns false if the nick is already in the table, true otherwise
 */
private static boolean add_nick(String nick, ClientConn c) {
    if (nicks.containsKey(nick)) {
        return false;
    } else {
        nicks.put(nick, c);
        return true;
    }
}

public ChatServerProtocol(ClientConn c) {
    nick = null;
    conn = c;
}

private void log(String msg) {
    System.err.println(msg);
}

public boolean isAuthenticated() {
    return ! (nick == null);
}

/**
 * Implements the authentication protocol.
 * This consists of checking that the message starts with the NICK command
 * and that the nick following it is not already in use.
 * returns: 
 *  msg_OK if authenticated
 *  msg_NICK_IN_USE if the specified nick is already in use
 *  msg_SPECIFY_NICK if the message does not start with the NICK command 
 */
private String authenticate(String msg) {
    if(msg.startsWith("NICK")) {
        String tryNick = msg.substring(5);
        if(add_nick(tryNick, this.conn)) {
            log("Nick " + tryNick + " joined.");
            this.nick = tryNick;
            return msg_OK;
        } else {
            return msg_NICK_IN_USE;
        }
    } else {
        return msg_SPECIFY_NICK;
    }
}

/**
 * Send a message to another user.
 * @recepient contains the recepient's nick
 * @msg contains the message to send
 * return true if the nick is registered in the hash, false otherwise
 */
private boolean sendMsg(String recipient, String msg) {
    if (nicks.containsKey(recipient)) {
        ClientConn c = nicks.get(recipient);
        c.sendMsg(nick + ": " + msg);
        return true;
    } else {
        return false;
    }
}

/**
 * Process a message coming from the client
 */
public String process(String msg) {
    if (!isAuthenticated()) 
        return authenticate(msg);

    String[] msg_parts = msg.split(" ", 3);
    String msg_type = msg_parts[0];

    if(msg_type.equals("MSG")) {
        if(msg_parts.length < 3) return msg_INVALID;
        if(sendMsg(msg_parts[1], msg_parts[2])) return msg_OK;
        else return msg_SEND_FAILED;
    } else {
        return msg_INVALID;
    }
 }
}

class ClientConn implements Runnable {
private Socket client;
private BufferedReader in = null;
private PrintWriter out = null;

ClientConn(Socket client) {
    this.client = client;
    try {
        /* obtain an input stream to this client ... */
        in = new BufferedReader(new InputStreamReader(
                    client.getInputStream()));
        /* ... and an output stream to the same client */
        out = new PrintWriter(client.getOutputStream(), true);
    } catch (IOException e) {
        System.err.println(e);
        return;
    }
}

public void run() {
    String msg, response;
    ChatServerProtocol protocol = new ChatServerProtocol(this);
    try {
        /* loop reading lines from the client which are processed 
         * according to our protocol and the resulting response is 
         * sent back to the client */
        while ((msg = in.readLine()) != null) {
            response = protocol.process(msg);
            out.println("SERVER: " + response);
        }
    } catch (IOException e) {
        System.err.println(e);
    }
}

public void sendMsg(String msg) {
    out.println(msg);
 }
}

ChatClient.java:

/* ChatClient.java */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;

import java.net.Socket;
import java.net.UnknownHostException;

public class ChatClient {
private static int port = 1001; /* port to connect to */
private static String host = "localhost"; /* host to connect to */

private static BufferedReader stdIn;

private static String nick;

/**
 * Read in a nickname from stdin and attempt to authenticate with the 
 * server by sending a NICK command to @out. If the response from @in
 * is not equal to "OK" go bacl and read a nickname again
 */
private static String getNick(BufferedReader in, 
                              PrintWriter out) throws IOException {
    System.out.print("Enter your nick: ");
    String msg = stdIn.readLine();
    out.println("NICK " + msg);
    String serverResponse = in.readLine();
    if ("SERVER: OK".equals(serverResponse)) return msg;
    System.out.println(serverResponse);
    return getNick(in, out);
}

public static void main (String[] args) throws IOException {

    Socket server = null;

    try {
        server = new Socket(host, port);
    } catch (UnknownHostException e) {
        System.err.println(e);
        System.exit(1);
    }

    stdIn = new BufferedReader(new InputStreamReader(System.in));

    /* obtain an output stream to the server... */
    PrintWriter out = new PrintWriter(server.getOutputStream(), true);
    /* ... and an input stream */
    BufferedReader in = new BufferedReader(new InputStreamReader(
                server.getInputStream()));

    nick = getNick(in, out);

    /* create a thread to asyncronously read messages from the server */
    ServerConn sc = new ServerConn(server);
    Thread t = new Thread(sc);
    t.start();

    String msg;
    /* loop reading messages from stdin and sending them to the server */
    while ((msg = stdIn.readLine()) != null) {
        out.println(msg);
    }
  }
}

class ServerConn implements Runnable {
private BufferedReader in = null;

public ServerConn(Socket server) throws IOException {
    /* obtain an input stream from the server */
    in = new BufferedReader(new InputStreamReader(
                server.getInputStream()));
}

public void run() {
    String msg;
    try {
        /* loop reading messages from the server and show them 
         * on stdout */
        while ((msg = in.readLine()) != null) {
            System.out.println(msg);
        }
    } catch (IOException e) {
        System.err.println(e);
    }
  }
}

Редактировать

Из комментария

Это то, чтопроисходит, когда я запускаю код:

на стороне клиента:

Enter your nick: learnHK
hello
SERVER: INVALID COMMAND
not working?
SERVER: INVALID COMMAND

и на стороне сервера:

Nick learnHK joined.

И это все.Клиент не получает ответное сообщение «ОК» с сервера и не может начать чат.Спасибо.

Ответы [ 2 ]

1 голос
/ 04 января 2012

использование

MSG TARGER_USERNAME message_here
0 голосов
/ 02 декабря 2011

Ваша проблема в том, что это не простой чат-сервер, где вы просто пишете все, что хотите, и он отправляется обратно. Сервер хочет конкретные команды.

Вот пример сеанса, который я только что провел:

Enter your nick: arrow
hello
SERVER: INVALID COMMAND
MSG arrow hello
arrow: hello
SERVER: OK

Как видите, когда я отправляю только строку "привет", я получаю сообщение об ошибке. Но когда я использую «MSG arrow hello», он анализируется сервером как правильная команда.

...