【问题标题】:Chat Program: Client to Client Chat聊天程序:客户对客户聊天
【发布时间】:2014-05-10 13:10:39
【问题描述】:

目前我正在使用 Java 开发这个迷你聊天程序,其中多个用户应该能够登录聊天程序并聊天。现在我的程序所做的是将用户(客户端)登录到服务器,并且他们所说的任何内容都会被服务器回显。我想要做的是能够直接发送与另一个客户聊天的请求。

我的想法是创建一个包含客户端用户名及其套接字的哈希映射。当客户端请求与另一个客户端聊天时,它会在 HashMap 中查找该用户的用户名,如果另一个客户端同意聊天,则它会连接套接字。 我不知道如何实现这一点,而且我的程序只接受用户的一个输入并从服务器返回它,然后它停止我不知道为什么。我一直在努力让它工作一段时间,开始让我头疼。

代码如下:

客户端类:

package source;

import java.io.*;
import java.util.*;
import java.net.*;

public class Client implements Runnable {
    private Socket socket;
    private DataOutputStream dout;
    private DataInputStream din;
    // Constructor

    public Client() {
        // Code
    }

    public Client(String host, int port) {

        try {
            socket = new Socket(host, port);
            System.out.println("connected to " + socket);
            din = new DataInputStream(socket.getInputStream());
            dout = new DataOutputStream(socket.getOutputStream());
            new Thread(this).start();
        } catch (IOException ie) {
            System.out.println(ie);
        }
    }

    private void processMessage(String message) {
        try {
            dout.writeUTF(message);
        } catch (IOException ie) {
            System.out.println(ie);
        }
    }

    public void run() {
        try {
            while (true) {
                String message = din.readUTF();
                System.out.println(message);
            }
        } catch (IOException ie) {
            System.out.println(ie);
        }
    }

    public static void main(String[] args) throws IOException {
        while (true) {
            String prompt;
            Scanner clientPrompt = new Scanner(System.in);
            System.out.println("client> ");
            prompt = clientPrompt.next();
            if (prompt.equals("Emmanuel"))
                System.out.println("God With Us");
            else if (prompt.equals("goOnline")) {
                // Enter a host name
                // Enter a portNumber
                // Enter a userName
                String h, p, u;
                System.out.println("Enter hostname: ");
                h = clientPrompt.next();
                System.out.println("Enter portNumber: ");
                p = clientPrompt.next();
                System.out.println("Enter userName: ");
                u = clientPrompt.next();
                goOnline(h, p, u);
            } else if (prompt.equals("Exit")) {
                clientPrompt.close();
                System.exit(1);
            } else {
                System.out.println("Invalid Input, Try Again");
            }
        }
    }

    public static void goOnline(String host, String port, String userName) {
        int portNumber = Integer.parseInt(port);
        Client c = new Client(host, portNumber);
        c.processMessage("Username: " + userName);
        String prompt;
        Scanner clientPrompt = new Scanner(System.in);
        while (true) {

            prompt = clientPrompt.next();
            c.processMessage(prompt);
            c.run();
            if (prompt.equals("Exit")) {
                System.out.println("Bye Bye");
                clientPrompt.close();
            }
        }
    }
}

服务器类:

package source;

import java.io.*;
import java.net.*;
import java.util.*;

public class Server { // The ServerSocket we'll use for accepting new
                        // connections
    private ServerSocket ss;

    private HashMap<String, Socket> userInfo = new HashMap<String, Socket>();

    // A mapping from sockets to DataOutputStreams.
    private Hashtable<Socket, DataOutputStream> outputStreams = new Hashtable<Socket, DataOutputStream>();

    // Constructor and while-accept loop all in one.
    public Server(int port) throws IOException {
        // All we have to do is listen
        listen(port);
    }

    private void listen(int port) throws IOException {
        // ServerSocket
        ss = new ServerSocket(port);
        System.out.println("Listening on " + ss);
        while (true) {
            Socket s = ss.accept();
            System.out.println("Connection from " + s);
            DataOutputStream dout = new DataOutputStream(s.getOutputStream());
            DataOutputStream userInfo = new DataOutputStream(s.getOutputStream());
            outputStreams.put(s, dout);
            outputStreams.put(s, userInfo);
            new ServerThread(this, s);
        }
    }

    Enumeration<DataOutputStream> getOutputStreams() {
        return outputStreams.elements();
    }

    void sendToAll(String message) {
        for (Enumeration<DataOutputStream> e = getOutputStreams(); e.hasMoreElements();) {
            // Output Stream
            DataOutputStream dout = (DataOutputStream) e.nextElement();
            // Send Message
            try {
                dout.writeUTF(message);
            } catch (IOException ie) {
                System.out.println(ie);
            }
        }
    }

    // Remove socket,
    void removeConnection(Socket s) {
        // Synchronize
        synchronized (outputStreams) {
            // Tell the world
            System.out.println("Removing connection to " + s);
            // Remove it from hashtable
            outputStreams.remove(s);
            try {
                s.close();
            } catch (IOException ie) {
                System.out.println("Error closing " + s);
                ie.printStackTrace();
            }
        }
    }

    void addInfo(String user, Socket s) {
        userInfo.put(user, s);
    }

    // Main
    static public void main(String args[]) throws Exception {
        // Get port
        int port = Integer.parseInt(args[0]);
        // Create Server object
        new Server(port);
    }
}

服务器线程:

package source;

import java.io.*;
import java.util.*;
import java.net.*;

public class ServerThread extends Thread { // The Server that spawned us
    private Server server;
    private Socket socket;

    public ServerThread(Server server, Socket socket) {
        this.server = server;
        this.socket = socket;
        start();
    }

    public void run() {
        try {
            DataInputStream din = new DataInputStream(socket.getInputStream());
            while (true) {
                String message = din.readUTF();
                StringTokenizer stt = new StringTokenizer(message, " ");
                while (stt.hasMoreTokens()) {
                    String token = stt.nextToken();
                    if (token.equals("Username:")) {
                        String username = stt.nextToken();
                        server.addInfo(username, socket);
                    }
                }
                System.out.println("Sending " + message);

                server.sendToAll(message);
                if (message.equals("Exit")) {
                    System.out.println("Bye Bye");
                    server.removeConnection(socket);
                    System.exit(1);
                }
            }
        } catch (EOFException ie) {
        } catch (IOException ie) {
            ie.printStackTrace();
        } finally {
            server.removeConnection(socket);
        }
    }
}

【问题讨论】:

  • 您能否重新格式化您的代码以不使用任何制表符?现在,由于您的编辑器和 StackOverflow 之间对制表符的不同解释,大括号很不稳定,因此很难弄清楚您的代码在做什么。
  • 没关系,我不再使用此代码,但无论如何感谢@WarrenDew
  • 请注意标签不是关键字。在标签列表中塞满与您的问题相同的词(客户端、服务器、套接字、对等点)将无助于对其进行分类。请务必阅读选择标签时出现的说明!
  • 首先不要直接调用run()方法来启动线程,而不是使用start()方法。

标签: java sockets


【解决方案1】:

我的程序只接受用户的一个输入并从服务器返回它,然后它停止了我不知道为什么?

只需在客户端进行如下所述的一项更改即可解决上述问题。

public void run() {
    try {
        // while (true) { // remove an infinite loop that will block 
                          // the client thread to accept next message
        String message = din.readUTF();
        System.out.println(message);
        // }
    } catch (IOException ie) {
        System.out.println(ie);
    }
}

怀疑:(客户端)

  • 你已经启动了一个线程那你为什么要直接调用run()方法。

【讨论】:

    猜你喜欢
    • 2015-07-03
    • 2021-02-05
    • 2015-10-12
    • 2011-01-04
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多