簡體   English   中英

Java 服務器 - 多個端口?

[英]Java Server - Multiple ports?

我即將對服務器進行編程,但我想知道我的想法是否可行。 我的程序將輸出到多個端口上的多個客戶端 - 每個端口可以被多個客戶端訪問。

通常我會使用線程套接字服務器,但在這種情況下,我需要它為多個端口工作。 我想到的用法是在下面的模糊偽代碼中:

  • 啟動服務器
  • 偵聽多個端口上的傳入連接
  • 識別正在連接的端口
    • 如果端口 1,則啟動一個線程監聽客戶端並輸出消息類型x
    • 如果是端口 2,則啟動一個線程監聽客戶端並輸出消息類型y

希望這是有道理的,你可以看到我在做什么。 簡單地說:偵聽選定的端口,根據正在連接的端口創建線程套接字連接。

這是可行的,還是我最終會使用多線程線程套接字服務器?

編輯:更改措辭以更好地反映問題。

單個ServerSocket實例不可能偵聽多個端口。 您當然可以有多個ServerSocket 但是,正如您已經知道的, ServerSocket.accept阻塞。

您可以使用的是ServerSocketChannel 它們以類似的方式使用,但不會阻塞。

如果在調用ServerSocketChannel.accept時沒有掛起的連接,則它只返回 null。

您可以與Selector一起使用,該Selector接受一組通道並阻塞,直到至少有一個具有掛起的連接。

我不記得如何使用它們的細節,但這個似乎是一個體面的代碼示例。

編輯:這是我自己的例子(偽ish)

Selector selector = Selector.open();

int[] ports = {4000,4001,6000};

for (int port : ports) {
   ServerSocketChannel server = ServerSocketChannel.open();
   server.configureBlocking(false);

   server.socket().bind(new InetSocketAddress(port));
// we are only interested when accept evens occur on this socket
   server.register(selector, SelectionKey.OP_ACCEPT); 
}

while (selector.isOpen()) {
   selector.select();
   Set readyKeys = selector.selectedKeys();
   Iterator iterator = readyKeys.iterator();
   while (iterator.hasNext()) {
      SelectionKey key = (SelectionKey) iterator.next();
      if (key.isAcceptable()) {
         SocketChannel client = server.accept();
         Socket socket = client.socket();
// create new thread to deal with connection (closing both socket and client when done)
      }
   }
}

// tidy up selector and channels

你好,讓我直說吧。 您想要做的是創建一個可以偵聽多個端口的服務器,當您獲得新連接時,您希望能夠知道該連接使用了哪個端口,這是正確的嗎? 好吧,如果是這種情況,您可以使用java.nio包輕松完成此操作。

我們將使用Selector進行准備選擇,並使用ServerSocketChannel來偵聽傳入的連接。

首先我們需要聲明我們的Selector

Selector selector = Selector.open();

現在讓我們創建一個要監聽的端口列表並開始監聽它們。

int ports[] = new int[] { 1234, 4321 };

// loop through each port in our list and bind it to a ServerSocketChannel
for (int port : ports) {
    ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(false);
    serverChannel.socket().bind(new InetSocketAddress(port));
    serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}

現在是SelectionKey處理過程。

while (true) {
    selector.select();

    Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
    while (selectedKeys.hasNext()) {
        SelectionKey selectedKey = selectedKeys.next();

        if (selectedKey.isAcceptable()) {
            SocketChannel socketChannel = ((ServerSocketChannel) selectedKey.channel()).accept();
            socketChannel.configureBlocking(false);
            switch (socketChannel.socket().getPort()) {
                case 1234:
                    // handle connection for the first port (1234)
                    break;
                case 4321:
                    // handle connection for the secon port (4321)
                    break;
            }
        } else if (selectedKey.isReadable()) {
            // yada yada yada
        }
    }
}

也許這樣簡單的任務不需要 switch 語句,但它是為了便於閱讀和理解。

請記住,此服務器以非阻塞異步方式設置,因此您執行的所有 I/O 調用都不會阻塞當前線程。 所以不要SelectionKey處理過程中啟動任何新線程。

另外,我知道這並不能完全回答您的問題(可能,也可能沒有),但實際上它會讓您了解如何使用java.nio包來創建可以偵聽的非阻塞異步服務器在多個端口上。

您不能偵聽所有端口,但可以偵聽一組端口。 為您要偵聽的每個端口創建一個ServerSocket ( http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29 ),並接受每個端口上的連接.

NIO 應該可以做到這一點,但是我認為沒有充分的理由避免每個偵聽器擁有一個線程,除非您有超過 1K 的端口。

你真的需要多個監聽端口嗎? 在大多數情況下,一個端口應該可以支持所有類型的客戶端並讓客戶端告訴服務器(或服務器確定需要哪種類型的連接)

我不認為您可以收聽所有端口,不。 對於操作系統來說,這將是非常昂貴的,所以這根本不是端口偵聽的工作方式。

如果多個應用程序同時偵聽“所有”端口,網絡子系統應該將傳入的數據包傳送到哪個應用程序呢?

暫無
暫無

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

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