创建多线程Java服务器聊天应用程序。

时间:2014-10-11 05:25:41

标签: java multithreading sockets

我正在尝试用Java实现多线程服务器聊天应用程序 该程序创建了一个线程并等待客户端连接。连接客户端后,它会创建另一个线程并等待另一个客户端连接。

这是我的ChatServer.java

package com.chat.server;



import java.io.InputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.InetAddress;
import java.net.ServerSocket;



/**
 * <p>The chat server program</p>
 * This class is a Thread that recieves connection
 * from different clients and handles them is separate
 * Thread.
 *
 * @author Aditya R.Singh
 * @version 1.0.0
 * @since 1.0.0
 */
class ChatServer extends Thread {

    private int port;                    // The port number to listen at.
    private String ip;                   // To store the IP address.
    private Socket socket;               // Socket connection with different clients.
    private InetAddress inet;            // Handling Client Address.
    private ServerSocket serverSocket;   // The server socket used by clients to connect.



    /**
     * This is solely intended for instantiation purpose.
     * 
     * @param PORT - The port number to listen for client requests
     */
    ChatServer(final int PORT) {


        /* Initiallizing all instance variables to null. */
        ip = null;
        inet = null;
        socket = null;
        serverSocket = null;

        /* Initiallizing the port number. */
        port = PORT;
    }



    /**
     * This method creates a connection between server and client.
     * 
     * @throws java.io.IOException
     */
    private void createConnection() throws IOException {

        serverSocket = new ServerSocket(port);  // Listen to the required port. 
        socket = serverSocket.accept();         // Accept the client connection.
    }



    /**
     * This method sets the IP address.
     */
    private void setIP() {

        inet = socket.getInetAddress();
        ip = new String(inet.getHostAddress());
    }



    /**
     * This method returns the IP address.
     *
     * @return IP address.
     */
    public String getIP() {

        return ip;
    }



    /**
     * This method checks if the socket has been connected
     * with any client.
     *
     * @return True if the client has been connected, else false
     */
    public boolean isConnected() {

        if(socket == null)
            return false;
        return true;
    }



    /**
     * This method returns the InputStream
     * from the Socket.
     * 
     * @return InputStream if Socket has been connected to the client, else null
     * @see java.io.InputStream
     */
    public InputStream getInputStream() throws IOException {

        if(socket == null)
            return null;
        return socket.getInputStream();
    }



    @Override
    public void run() {

        try {

            createConnection();
            setIP();
        } catch(IOException exception) {

            exception.printStackTrace();
        }
    }
}  

这是我的Server.java

package com.chat.server;



/** 
 * <p>The Server app</p> 
 * This is the controller for accepting connections.
 *
 * @author Aditya R.Singh 
 * @version 1.0.0
 * @since 1.0.0
 */
public class Server {


    /**
     * The port at which clients will connect.
     */
    public static final int PORT = 6005;          



    /**
     * For instantiation purpose.
     */
    public Server() {


    }



    public static void main(String[] args) {


        /* Keep accepting connections. */
        while(true) {

            ChatServer chat = new ChatServer(PORT); // Connecting port.
            chat.start();

            while(!chat.isConnected())
                /* This is a false loop. Intended to keep running unless another client is not requesting to connect. */;

            System.out.println("We connected to: "+chat.getIP());   
        }
    }
}  

代码编译得很好 在运行代码时:

java com.chat.server.Server  

似乎该程序正在侦听客户端进行连接。但是在连接到客户端之后,它应该打印客户端的IP地址,然后为另一个客户端创建另一个线程。但它不会打印客户端的IP。

这是我的Client.java

package com.chat.client;



import java.net.Socket;
import java.io.IOException;



public class Client {

    public static void main(String[] args) {

        Socket socket = null;


        try {

            socket = new Socket("127.0.0.1", 6005);
            System.out.println("Socket connected.");
        } catch(IOException ex) {

            ex.printStackTrace();
        }
    }
}  

客户端连接到服务器,必须打印Socket connected。客户这样做。客户端工作正常:

java com.chat.client.Client  
Socket connected.  

但服务器应用程序不会打印客户端的IP地址。为什么这样?

2 个答案:

答案 0 :(得分:1)

这是竞争条件。行socket = serverSocket.accept();导致while(!chat.isConnected())循环在调用方法'setIP()'之前终止。验证这是导致问题的原因的一种快速方法是更改​​此方法:

public boolean isConnected() {
    if(socket == null)
        return false;
    return true;
}

public boolean isConnected() {
    if(socket == null || ip == null)
        return false;
    return true;
}

为了解决问题,您应该确保设置IP的代码和检查其连接的代码是否使用synchronized关键字。另外,请注意while(!chat.isConnected())循环没有暂停,这意味着它需要尽可能多的CPU ...这绝对不是好事。

查看@Michael Petch为正确实施聊天服务器而发布的链接。

答案 1 :(得分:1)

这不是完整的代码

package demo;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;



public class MultithreadedServer {

    public static final int PORT = 10000;

    public static void main(String[] args) {
        try(ServerSocket server = new ServerSocket(PORT)) {
            while(true){
                Socket connection = server.accept();
                Thread client = new ClientThread(connection);
                client.start();
            }
        } catch (IOException ex) {
            System.out.println("Error start server");
        }
    }

}

class ClientThread extends Thread {
    private Socket connection;

    public ClientThread(Socket connection) {
        this.connection = connection;
    }

    @Override
    public void run(){
        //Do communication with client
    }

}