Запуск клиент-серверной программы чата - PullRequest
0 голосов
/ 28 июня 2011

Это один из наиболее распространенных сценариев применения, который можно найти по всей сети. и я не задаю никаких вопросов о кодах java, которые я сделал, потому что мне удалось запустить его на моем ноутбуке, где находится как клиентская, так и серверная часть файла .java. Скорее у меня были проблемы с тем, чтобы заставить его работать между двумя компьютерами. Я попытался установить физическое соединение, используя перекрестный кабель для соединения двух компьютеров, и провел тест, чтобы убедиться, что передача файлов прошла успешно, однако он сохранил одну серверную часть файла .java на одном компьютере и клиентскую часть на другом Сначала я попытался запустить сервер, а затем клиента, но он получил ошибку «Отказано в доступе».

Для справки вот мои два файла .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 = 5000; /* port to connect to */
private static String host = "localhost"; /* host to connect to (server's IP)*/
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);
}
}
}

и вот 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 = 5000; /* 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);
}
}

Теперь, что мне делать, чтобы запустить эти два файла с двух компьютеров, если у меня уже есть настройка физического соединения (TCP / IP) ??

Заранее спасибо ...:)

Ответы [ 3 ]

2 голосов
/ 28 июня 2011

Похоже, что это проблема брандмауэра. Вы пытались открыть отверстие в брандмауэре для порта 1001?

0 голосов
/ 28 июня 2011

, как указано в комментарии, вы не должны использовать порт
1) если вам отказывают в соединении, вам следует правильно проверить исключение, нужно ли клиентской программе время на создание исключения (это означает, что запрос отправляется на сервер, а затем он отказывает в соединении), в этом случае вам следует попробовать java.policy
поместите следующее в файл с именем java.policy </p> <p>grant {<br> permission java.net.SocketPermission "<em>:1024-65535", "connect,accept";<br> permission java.net.SocketPermission "</em>:80", "connect";<br> permission java.io.FilePermission "<em>", "read,write,delete";<br> permission java.security.SecurityPermission "</em>";<br> };
при компиляции используйте этот флаг -Djava.security.policy=java.policy
более того, вы также должны попробовать -Djava.rmi.server.hostname = IP, где IP - это clien-ip для client.java и server-ip для server.java

2) если вы сразу получаете исключение на стороне клиента, то ваш запрос не выходит за пределы вашего компьютера, поэтому у клиента есть некоторые проблемы.
проверьте исключение должным образом и опубликуйте их здесь.

3) хотя у меня нет ошибки отказа в доступе, но, похоже, есть проблема с портом, которая может быть решена с помощью политики или порта> 1024.
опубликуйте, что вы получаете сейчас.

0 голосов
/ 28 июня 2011

Вы также посмотрели на java.policy и убедитесь, что он настроен на то, чтобы локальная кодовая база открывала сокеты?

...