对于最新的稳定版本,请使用 Spring Integration 6.4.0! |
UDP 适配器
本节介绍如何配置和使用 UDP 适配器。
出站 UDP 适配器 (XML 配置)
以下示例配置 UDP 出站通道适配器:
<int-ip:udp-outbound-channel-adapter id="udpOut"
host="somehost"
port="11111"
multicast="false"
socket-customizer="udpCustomizer"
channel="exampleChannel"/>
设置为 时,还应在 host 属性中提供多播地址。multicast true |
UDP 是一种高效但不可靠的协议。
Spring 集成添加了两个属性来提高可靠性:和 。
设置为 时,适配器在消息数据前面有一个 length 字段(按网络字节顺序排列的四个字节)。
这使接收方能够验证收到的数据包的长度。
如果接收系统使用的缓冲区太短而无法包含数据包,则数据包可能会被截断。
标头提供了一种检测此情况的机制。check-length
acknowledge
check-length
true
length
从版本 4.3 开始,您可以将 设置为 ,在这种情况下,操作系统会选择端口。
可以通过在适配器启动后调用 来发现所选端口,并返回 。port
0
getPort()
isListening()
true
从版本 5.3.3 开始,您可以添加 bean 以在创建后对其进行修改(例如, call )。SocketCustomizer
DatagramSocket
setTrafficClass(0x10)
以下示例显示了一个出站通道适配器,该适配器向数据报数据包添加了长度检查:
<int-ip:udp-outbound-channel-adapter id="udpOut"
host="somehost"
port="11111"
multicast="false"
check-length="true"
channel="exampleChannel"/>
数据包的接收方还必须配置为预期长度在实际数据之前。
对于 Spring 集成 UDP 入站通道适配器,请设置其属性。check-length |
第二个可靠性改进允许使用应用程序级确认协议。 接收方必须在指定时间内向发送方发送确认。
以下示例显示了一个出站通道适配器,该适配器向数据报数据包添加长度检查并等待确认:
<int-ip:udp-outbound-channel-adapter id="udpOut"
host="somehost"
port="11111"
multicast="false"
check-length="true"
acknowledge="true"
ack-host="thishost"
ack-port="22222"
ack-timeout="10000"
channel="exampleChannel"/>
设置为 表示数据包的接收方可以解释添加到包含确认数据(主机和端口)的数据包的报头。
最有可能的是,接收者是 Spring 集成入站通道适配器。acknowledge true |
当 multicast 为 true 时,附加属性 () 指定必须在 .min-acks-for-success ack-timeout |
从版本 4.3 开始,您可以将 设置为 ,在这种情况下,操作系统会选择端口。ackPort
0
出站 UDP 适配器 (Java 配置)
以下示例演示如何使用 Java 配置出站 UDP 适配器:
@Bean
@ServiceActivator(inputChannel = "udpOut")
public UnicastSendingMessageHandler handler() {
return new UnicastSendingMessageHandler("localhost", 11111);
}
(或用于多播)。MulticastSendingChannelAdapter
出站 UDP 适配器 (Java DSL 配置)
以下示例说明如何使用 Java DSL 配置出站 UDP 适配器:
@Bean
public IntegrationFlow udpOutFlow() {
return f -> f.handle(Udp.outboundAdapter("localhost", 1234)
.configureSocket(socket -> socket.setTrafficClass(0x10)))
.get();
}
入站 UDP 适配器 (XML 配置)
以下示例说明如何配置基本的单播入站 udp 通道适配器。
<int-ip:udp-inbound-channel-adapter id="udpReceiver"
channel="udpOutChannel"
port="11111"
receive-buffer-size="500"
multicast="false"
socket-customizer="udpCustomizer"
check-length="true"/>
以下示例说明如何配置基本的多播入站 udp 通道适配器:
<int-ip:udp-inbound-channel-adapter id="udpReceiver"
channel="udpOutChannel"
port="11111"
receive-buffer-size="500"
multicast="true"
multicast-address="225.6.7.8"
check-length="true"/>
默认情况下,不对入站数据包执行反向 DNS 查找:在未配置 DNS 的环境中(例如 Docker 容器),这可能会导致连接延迟。
要将 IP 地址转换为主机名以用于邮件报头,可以通过将属性设置为 来覆盖默认行为。lookup-host
true
从版本 5.3.3 开始,您可以添加 bean 以在创建后对其进行修改。
它被调用用于接收套接字和为发送 ack 创建的任何套接字。SocketCustomizer
DatagramSocket
入站 UDP 适配器 (Java 配置)
以下示例显示如何使用 Java 配置入站 UDP 适配器:
@Bean
public UnicastReceivingChannelAdapter udpIn() {
UnicastReceivingChannelAdapter adapter = new UnicastReceivingChannelAdapter(11111);
adapter.setOutputChannelName("udpChannel");
return adapter;
}
以下示例显示了如何使用 Java DSL 配置入站 UDP 适配器:
入站 UDP 适配器 (Java DSL 配置)
@Bean
public IntegrationFlow udpIn() {
return IntegrationFlow.from(Udp.inboundAdapter(11111))
.channel("udpChannel")
.get();
}
服务器侦听事件
从版本 5.0.2 开始,当入站适配器启动并开始侦听时,会发出 a。
当适配器配置为侦听 port 时,这很有用,这意味着操作系统选择端口。
如果您需要在启动将连接到套接字的其他进程之前等待,也可以使用它代替 polling 。UdpServerListeningEvent
0
isListening()
高级出站配置
() 有 和 选项。<int-ip:udp-outbound-channel-adapter>
UnicastSendingMessageHandler
destination-expression
socket-expression
您可以使用 hardcoded - 对的运行时替代方案来确定传出数据报数据包的目标地址(使用评估上下文的根对象)。
表达式的计算结果必须为 URI 样式的 、 a (请参阅 RFC-2396) 或 a 。
您还可以将此表达式使用 inbound 标头。
在框架中,当我们在 中接收数据报并将其转换为消息时,它会填充此标头。
标头值正是传入数据报的结果。destination-expression
host
port
requestMessage
URI
String
SocketAddress
IpHeaders.PACKET_ADDRESS
DatagramPacketMessageMapper
UnicastReceivingChannelAdapter
DatagramPacket.getSocketAddress()
使用 ,出站通道适配器可以使用(例如)入站通道适配器套接字通过接收数据的同一端口发送数据报。
当我们的应用程序作为 UDP 服务器工作,而客户端在网络地址转换 (NAT) 后面运行时,它非常有用。
此表达式的计算结果必须为 。
该用作评估上下文的根对象。
不能将参数与 和 参数一起使用。
以下示例说明如何使用转换为大写并使用套接字的转换器配置 UDP 入站通道适配器:socket-expression
DatagramSocket
requestMessage
socket-expression
multicast
acknowledge
<int-ip:udp-inbound-channel-adapter id="inbound" port="0" channel="in" />
<int:channel id="in" />
<int:transformer expression="new String(payload).toUpperCase()"
input-channel="in" output-channel="out"/>
<int:channel id="out" />
<int-ip:udp-outbound-channel-adapter id="outbound"
socket-expression="@inbound.socket"
destination-expression="headers['ip_packetAddress']"
channel="out" />
以下示例显示了 Java DSL 的等效配置:
@Bean
public IntegrationFlow udpEchoUpcaseServer() {
return IntegrationFlow.from(Udp.inboundAdapter(11111).id("udpIn"))
.<byte[], String>transform(p -> new String(p).toUpperCase())
.handle(Udp.outboundAdapter("headers['ip_packetAddress']")
.socketExpression("@udpIn.socket"))
.get();
}