运行客户端 - 服务器聊天程序

时间:2011-06-28 17:05:37

标签: java client-server chat

这是可以在网络上找到的最常见的应用程序方案之一。我不会问我有关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 个答案:

答案 0 :(得分:2)

听起来很可能是防火墙问题。您是否尝试在防火墙上为端口1001打开一个洞?

答案 1 :(得分:0)

您是否也查看过java.policy并确保将其配置为允许本地代码库打开套接字?

答案 2 :(得分:0)

如评论中所述,您不应该使用port&lt; 1025适用于您的应用程序,因为它们始终用于deamon进程。但是你应该像这样测试你的程序
1)如果连接被拒绝,那么你应该正确检查异常,是否客户端程序在生成异常之前需要时间(这意味着请求将转到服务器然后它会拒绝连接),在这种情况下你应该尝试java.policy 的文件中

grant {
permission java.net.SocketPermission ":1024-65535", "connect,accept";
permission java.net.SocketPermission "
:80", "connect";
permission java.io.FilePermission "", "read,write,delete";
permission java.security.SecurityPermission "
";
};

编译时使用此标志-Djava.security.policy=java.policy
你应该尝试-Djava.rmi.server.hostname = IP,其中IP是client.java的clien-ip和server.java的server-ip

2)如果您在客户端立即出现异常,那么您的请求不会出现在您的电脑之外,因此客户端存在一些问题。
正确检查异常并将其张贴在此处。

3)虽然我没有访问被拒绝错误,但它似乎有端口问题可能使用策略或端口&gt; 1024解决。
发布你现在得到的东西。

相关问题