Java帮助为每个连接的用户创建一个新套接字

时间:2013-04-16 03:47:37

标签: java multithreading sockets stream connection

我正在创建一个聊天服务器,我无法建立多个连接,我相信这是因为只有一个套接字。我已经读过一个线程一次能够处理多个套接字连接但是每个客户端必须拥有它自己的套接字。像一个墙上插座。每个插头必须有1个插座。如何为每个客户端创建一个用于与服务器通信的套接字?我将提供一些代码来帮助你们帮助你们。这是接受单个套接字(连接)的地方。

 private void waitForConnection() throws IOException
 {
     connection = server.accept();
     showMessage("\nNow connected to " + connection.getInetAddress().toString());
     clientCount += 1;
 }

以下是从服务器启动时调用代码的地方:

public void startRunning()
{
  try
  {
     server = new ServerSocket(1337, 10);
     while(true)
     {
        try
        {
            showMessage("Waiting For a Player To Connect...");
            waitForConnection();
            setupStreams();
            whileChatting();

        }
        catch(EOFException eofException)
        {
           showMessage("\n Server ended the connection! ");
        }
        finally
        {
           closeConnections();
        }
     }
  }
  catch(IOException ioException)
  {
     ioException.printStackTrace();
  }
}

现在,此代码适用于第一个连接的客户端。所有其他人根本无法连接。提前致谢所有提交答案的人。

3 个答案:

答案 0 :(得分:1)

你应该让一个线程始终执行socket.accept()。那就是:

  • 每当您收到客户(通过socket.accept())时,您应该
    • 开始一个新的Thread,从现在起将照顾该客户。 (我称之为Thread扩展课程ClientNanny);
    • 然后再次运行socket.accept()

这就是你的waitForConnection()方法的样子:

private List<ClientNanny> clients = new ArrayList<ClientNanny>();

private void waitForConnection() throws IOException
{
     while (true) { /* or some other condition you wish */
         connection = server.accept(); /* will wait here */
         /* this code is executed when a client connects... */

         showMessage("\nNow connected to " 
                                      + connection.getInetAddress().toString());

         ClientNanny nanny = new ClientNanny(connection); /* call a nanny to take
                                                             care of it */
         clients.add(nanny); /* make sure you keep a ref to it, just in case */
         nanny.start(); /* tell nanny to get to work as an independent thread */
         clientCount += 1; /* you dont need this: use clients.size() now */
     }
}

如果您没有注意到,ClientNanny应该是这样的:

class ClientNanny extends Thread {
    ClientNanny(Socket baby) {
        this.myBaby = baby;
    }
    @Override
    public void run() {
        bed.put(myBaby); /* and probably other commands :) */
    }
}

现在,你应该注意到下面突出显示的代码......

try
{
    showMessage("Waiting For a Player To Connect...");
    waitForConnection();
    setupStreams();  /* <--------- THIS LINE! HI! I'M A HIGHLIGHT! */
    whileChatting(); /* <--------- THIS LINE! HI! I'M A HIGHLIGHT TOO! */
}

按照我的建议更改waitForConnection()时不会执行(因为waitForConnection()会继续在while(true)循环内滚动)。也许你可以把socket.accept()放在自己的线上......无论如何,我相信你可以从现在开始接受它,是吗?

PS。:作为最终指针,上面的解决方案使用new Thread()(或new ClientNanny()),因为这是解释问题的最简单方法。但是,非常优化的解决方案可能涉及使用ExecutorService(大致是一个线程池),如this answer中指出的那样。

答案 1 :(得分:0)

代码的整个结构是错误的:

waitForConnection();
setupStreams();
whileChatting();

这不能满足您的要求。你的循环应该旋转除了接受连接之外什么都不做,然后为处理该Socket上的所有I / O的每个循环启动一个新线程。请参阅Java教程的Custom Networking部分。

答案 2 :(得分:0)

您的套接字代码应该类似于PSEUDO-CODE:

create server socket
while true (or quit received) {
    accept connection
    spawn thread to handle communication
}

也就是说,您需要为每个连接生成一个线程。然后每个线程都可以执行whileChatting(),而不是占用主线程。

示例:

while (true) {
    try {
        // listen for client connections
        Socket s = svr.accept();

        // start a separate thread to handle this client's communications
        new ChatClientHandler(s).start();
    }
    catch (IOException e) {
        // print out the error, but continue!
        System.err.println(e);
    }
}