在服务器套接字上接受来自客户端的多个连接

Accepting multiple connections from clients on a serversocket

我刚开始使用套接字,对于我当前的项目,我需要能够从客户端控制我的程序,但是如果我的项目合作伙伴想要同时使用他的客户端,服务器不会发送他 "You are connected" 消息,如连接 class 中所示。所以我假设服务器不会同时接受多个客户端。我曾尝试使用 class 连接的线程,但也不会将消息 "You are connected" 发送到第二个客户端。我在这里做错了什么?

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

public class Listener extends Thread{

private ServerSocket server;
private int PORT;
public boolean running;

public Listener(int port){
    try{
        this.PORT = port;
        this.server = new ServerSocket(PORT,10);
    }catch (IOException e) {
        System.out.println("Could not create serverSocket...");
    }
}

@Override
public void run() {
    this.running = true;
    try{
        waitForConnection();
    }catch(IOException e){
        System.out.println("Could not accept connection request..");
        run();
    }


}
public void dispose(){
    try{
        System.out.println("DISPOSE");
        running = false;
        server.close();
    } catch (IOException i) {
        System.out.println("Could not close ServerSocket");
    }
}
private void waitForConnection() throws IOException{
    while(running){
        System.out.println("Waiting for connection");
        Socket client = server.accept();
        Runnable connection = new Connection(client);
        new Thread(connection).start();
    }
}       
}

这是我用来让多个用户同时连接的线程:

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

public class Connection extends Thread {
     Socket connection;
     private ObjectOutputStream output;
     private ObjectInputStream input;
     private boolean running;

     public Connection(Socket connect){
          this.connection = connect;
          try {
              setupStreams();
              whileListening();
          } catch (IOException e) {
                System.out.println("could not connect to: "+ connection.getInetAddress().getHostName());
    }
}

public void dispose(){
    try{
        output.close();
        input.close();
        connection.close();
        running = false;
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}   

private void whileListening(){
    String message = "You are connected! ";
    sendMessage(message);
    do{
        try{
            message = (String) input.readObject();
            checkMessage(message);
        }catch(ClassNotFoundException classNotFoundException){
            sendMessage("tf did you send? ");
        }catch (IOException e) {
            dispose();
            run();
        }
    }while(!message.equals("Client - END") && running == true);
}

private void setupStreams() throws IOException{
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();
    input = new ObjectInputStream(connection.getInputStream());
}

private  void sendMessage(String message){
    try {
        output.writeObject("Server - " + message+"\n");
        output.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void checkMessage(String text){
        //check the message
}
}     

编辑:附加信息

在第一个客户端连接之前,服务器控制台显示 "Waiting for connection",然后当第一个客户端连接时,客户端控制台显示 "You are connected",当第二个客户端连接时,控制台为黑色,当我关闭第一个客户端时,第二个客户端控制台显示 "You are connected",服务器控制台显示 "Waiting for connection",然后如果我也关闭第二个客户端,服务器控制台再次显示 "Waiting for connection"。

我想你必须先接受,然后你才开始跟帖。

例如,让我们假设这样的事情

  1. 在您的主 class 中,您获得了 ServerSocketFactory,然后是 ServerSocket。
  2. 然后,在(无休止的)循环中,您等待 ServerSocket.accept()
  3. 返回的新套接字
  4. 只有在那之后,你才能开始你的话题

这是来自 SSLServerSocket 的示例,其逻辑几乎相同(将其视为 pseudo-code)

    SSLContext sc = SSLContext.getInstance("TLS");
    (...)
    SSLServerSocketFactory ssf = sc.getServerSocketFactory();
    SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(portNumber);
    while (listening) {
        SSLSocket c = (SSLSocket) s.accept();
        log.info("Serving");
        new SimpleSSLServerSocketThread(c).start();
    }

public class Connection extends Thread 的构造函数中执行此 whileListening() 操作,因此构造函数永远不会结束,您需要覆盖 run() 函数并在那里执行此操作

@Override
public void run() {
    while(true) {
        try {
            whileListening();
        } catch(Exception e) {}
    }
}

像这样,它应该可以解决问题。