5

リクエストを受け入れてレスポンスを返すことができるスプリング統合フレームワークを使用して UDP サーバーを作成することは可能でしょうか。

TCP の場合、要求/応答処理を許可する TCP ゲートウェイがありますが、UDP では同様のことがわかりません。

UDP リスナーをセットアップしてパケットを受信するのは簡単ですが、定義済みの出力チャネルにしかルーティングできないため、応答を返す方法がわかりません。

また、トランスフォーマーは DatagramPacket オブジェクトを受信せず、データのみを受信するため、送信者の IP とポートは表示されません。

これが私の構成です:

<int:channel id="ChannelIn" />

<ip:udp-inbound-channel-adapter id="ChannelReceiver"
    channel="ChannelIn"
    port="5555"
    multicast="false"
    check-length="false" 
    pool-size="10"
    />

<int:transformer
    ref="datagramToPacketTransformer"
    input-channel="ChannelIn"
    output-channel="ChannelSA" 
    method="toPacket"/>

<int:channel id="ChannelSA" />

<int:service-activator id="ChannelActivator" 
    input-channel="ChannelSA"
    ref="PacketHandler"
    method="process"
/>
4

3 に答える 3

2

UDP を処理する方法を見つけました。以下は私の構成です

<int-ip:udp-inbound-channel-adapter id="ChannelReceiver"
                                    channel="serverBytes2StringChannel"
                                    port="9000"
                                    multicast="false"
                                    check-length="false" 
                                    pool-size="10"
                                    lookup-host="false"
/>

<int:transformer id="serverBytes2String"
                 input-channel="serverBytes2StringChannel"
                 output-channel="udpSA" 
                 expression="new String(payload)"

/>

<int:service-activator input-channel="udpSA" 
                       ref="deviceService" 
                       method="udpMessage"/>

そして、deviceServiceBeanには次のコードがあります:

 public Message udpMessage(Message message) {
        String response = "KO";
        try {
            response = process(message);
        } catch (Throwable th) {
            //do something
        }
        Message msg = MessageBuilder.withPayload(response.getBytes()).copyHeaders(message.getHeaders()).build();
        sendReply(msg);
        return null;
    }
    private void sendReply(Message message) {
        try {
            int port = (Integer) message.getHeaders().get("ip_port");
            String ip = (String) message.getHeaders().get("ip_address");
            InetAddress IPAddress = InetAddress.getByName(ip);

            byte[] sentence = (byte[]) message.getPayload();
            byte[] sendData = new byte[sentence.length];
            byte[] receiveData = new byte[1024];
            sendData = sentence;
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
            DatagramSocket clientSocket = new DatagramSocket();
            clientSocket.send(sendPacket);
            clientSocket.close();
        } catch (Exception ex) {
            throw new RuntimeException("KO");
        }
    }

これは私のパソコンでは完全に機能していますが、このコードを Amazon AWS にデプロイすると機能しません。プログラムがUDP 9000ポートでリッスンしているにもかかわらず、サーバー側で通信が受信されていないことがわかりました。その AWS インスタンスのすべての UDP ポートを許可しましたが、これは AWS セットアップの問題である可能性があります。

これを Amazon AWS で機能させる方法に関するヒントはありますか?

于 2013-10-12T07:58:41.743 に答える
1

ほぼ 2 年前に新機能 JIRA をオープンしました

https://jira.springsource.org/browse/INT-1809

しかし、投票もウォッチャーも受け取らなかったので、閉じました。

お気軽にコメントを追加してください。再開できます。

送信者のIPはメッセージヘッダーにありますが、彼のポートにはありません...

            message = MessageBuilder.withPayload(payload)
                    .setHeader(IpHeaders.HOSTNAME, hostName)
                    .setHeader(IpHeaders.IP_ADDRESS, hostAddress)
                    .build();

そのために新しい JIRA を開きたい場合は、2.2 に移行するのに十分な小さな変更です。まもなくリリースされる予定です (ただし、ゲートウェイは 2.2 を作成しません)。

https://jira.springsource.org/browse/INT

于 2012-09-27T14:59:11.107 に答える
-1

ありがとう、ゲイリー!

リモート IP アドレスがヘッダーにあることに気付きましたが、リモート ポートはそうではないので、いくつか変更を加えて追加しました。

Message が構築されている asyncSendMessage をオーバーライドするように UnicastRecomingChannelAdapter を拡張しました。DatagramPacketMessageMapper も拡張する必要がありました。UnicastRecomingChannelAdapter に DatagramPacketMessageMapper の独自の実装を挿入できればもっと簡単でしたが、それは不可能です。

次に、春の構成で私は削除しました

<ip:udp-inbound-channel-adapter id="ChannelReceiver"...>

定義し、以下を追加

<bean id="udpInboundChannelAdapterBean" 
          class="me.spring.integration.udp.UnicastReceivingChannelAdapterExt" init-method="run">
          <constructor-arg name="port" value="5555" />
          <property name="poolSize" value="10"/>
          <property name="lookupHost" value="false"/>
          <property name="outputChannel" ref="ChannelIn" />

まだ完全にテストする時間がありませんでしたが、これはうまくいくようです。

私の考えは、リモート IP とポート、および udpInboundChannelAdapterBean からの DatagramSocket 参照を使用して、応答をソケットに書き込むだけの新しいアクティベーション サービスを作成することです。

あなたが提案したように、リモートポート用の新しいjiraを開きます。

于 2012-09-27T17:54:45.583 に答える