簡體   English   中英

Java幫助為每個連接的用戶創建一個新的套接字

[英]Java help creating a new socket per connected user

我正在創建一個聊天服務器,但無法建立多個連接,我相信這是因為只有一個套接字。 我讀過,一個線程一次可以處理多個套接字連接,但是每個客戶端必須擁有自己的套接字。 像牆上的插座。 每個插頭必須有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();
  }
}

現在,此代碼對於第一個已連接的客戶端非常有效。 所有其他人根本無法連接。 在此先感謝所有提交答案的人。

您應該讓一個線程始終執行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 (大致是線程池),正如在此答案中迅速指出的那樣。

您的代碼的整個結構是錯誤的:

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

這不能滿足您的要求。 您的循環應該不做任何事情,只接受連接,然后為處理該套接字上所有I / O的每個線程啟動一個新線程。 請參閱Java教程的“ 定制網絡”部分。

您的套接字代碼應類似於以下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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM