2012-10-03 26 views
0

我有一個使用套接字I/O的Netty的服務器任務。它綁定到端口MY_PORT並從客戶端接收UDP消息。它響應這些客戶端,將消息發送回目標端口爲MY_PORT的客戶端。使用wireshark,我發現從我的服務器發出的數據包也有一個源端口MY_PORT。這一切工作正常。如何配置使用Netty發送UDP數據包的服務器的源端口?

服務器和客戶端之間的網絡負責人在負載均衡器中遇到了一些問題。他們說如果我的服務器發送給客戶端的UDP消息具有與用於目的地的源端口不同的源端口,它將幫助他們。

我已經看過Netty API,但我不知道我該如何做到這一點。看起來,因爲我已經綁定到本地端口,我必須將它用於傳出數據包?這是我的代碼的精簡版本。

import java.net.InetAddress; 
import java.net.InetSocketAddress; 
import java.net.SocketAddress; 
import java.net.UnknownHostException; 
import java.util.concurrent.Executors; 

import org.jboss.netty.bootstrap.ConnectionlessBootstrap; 
import org.jboss.netty.buffer.ChannelBuffer; 
import org.jboss.netty.buffer.ChannelBuffers; 
import org.jboss.netty.channel.Channel; 
import org.jboss.netty.channel.ChannelHandlerContext; 
import org.jboss.netty.channel.ChannelPipeline; 
import org.jboss.netty.channel.ChannelPipelineFactory; 
import org.jboss.netty.channel.Channels; 
import org.jboss.netty.channel.MessageEvent; 
import org.jboss.netty.channel.SimpleChannelHandler; 
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory; 

public class UdpServer { 

    private final int port; 
    private Channel serverChannel; 

    public UdpServer(int port) { 
     super(); 
     this.port = port; 
    } 

    public void start() { 
     NioDatagramChannelFactory serverChannelFactory = 
      new NioDatagramChannelFactory(Executors.newCachedThreadPool(), 1); 
     ConnectionlessBootstrap serverBootstrap = 
      new ConnectionlessBootstrap(serverChannelFactory); 
     serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() { 
      @Override 
      public ChannelPipeline getPipeline() { 
       return Channels.pipeline(new SimpleChannelHandler() { 
        @Override 
        public void messageReceived(ChannelHandlerContext ctx, 
         MessageEvent e) { 
         // TODO, handle message from client 
        } 
       }); 
      } 
     }); 
     serverBootstrap.setOption("reuseAddress", Boolean.TRUE); 
     final InetSocketAddress trafficAddress = new InetSocketAddress(port); 
     serverChannel = serverBootstrap.bind(trafficAddress); 
    } 

    public void sendMessage(byte[] message, String clientIp) 
     throws UnknownHostException { 
     // TODO, how do I control the source port of this packet?? 
     SocketAddress address = 
      new InetSocketAddress(InetAddress.getByName(clientIp), port); 
     ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(message); 
     serverChannel.write(buffer, address); 
    } 

} 

回答

2

您已經在使用bind()來設置本地地址。您可以使用connect()連接到特定的目標端口(一段「連接」概念)。在常規數據報套接字上,您可以在發送請求中包含遠程端口,但如果您使用的是write(),則不會。在這種情況下,您必須使用connect()

+0

所以,我仍然需要bind()調用來接收流量,但不使用從它返回的Channel對象。相反,每次我想將某個東西發送給客戶端時,我都會調用connect()。如果我有1000個客戶端,那麼我必須保留所有這些Channel對象,或者每次發送消息時創建一個新對象,這兩個對象看起來效率都不高。我的理解是正確的嗎? – wolfcastle

+0

就是這樣。 –

0

他們說,這將幫助他們,如果我的服務器發送到客戶端的UDP消息有比用於目的地的一個不同的源端口。

這聽起來像是對我的完整hooey。網絡管理員似乎不知道如何實際分配源/目標端口。即使客戶端使用系統分配的詩人而不是固定端口(他們可能應該這樣做),系統仍然可以分配與服務器使用的端口號相同的端口號。

但是,通過讓客戶端使用系統分配的端口而不是固定的端口,您可能可以關閉它們,或至少將它們移動到另一個問題上。除非有客戶端防火牆,當然...

+0

是的,我有同樣的想法。不幸的是,我對這個系統中的客戶端沒有任何控制權,並且系統中有防火牆,因此需要固定端口。 – wolfcastle

相關問題