UDP 回显
与 TCP 服务器示例类似,此程序将侦听指定的 IP 地址和端口,但这次是侦听 UDP 数据报。如果接收到数据,它将被回显到发送者的地址。
尽管 std.net 主要侧重于 TCP 的抽象(目前为止),我们仍然可以利用套接字编程通过 UDP 进行通信。
//! Start a UDP echo on an unused port.
//!
//! Test with
//! echo "hello zig" | nc -u localhost <port>
const std = @import("std");
const net = std.net;
const posix = std.posix;
const print = std.debug.print;
pub fn main() !void {
// adjust the ip/port here as needed
const addr = try net.Address.parseIp("127.0.0.1", 32100);
// get a socket and set domain, type and protocol flags
const sock = try posix.socket(
posix.AF.INET,
posix.SOCK.DGRAM,
posix.IPPROTO.UDP,
);
// for completeness, we defer closing the socket. In practice, if this is
// a one-shot program, we could omit this and let the OS do the cleanup
defer posix.close(sock);
try posix.bind(sock, &addr.any, addr.getOsSockLen());
var other_addr: posix.sockaddr = undefined;
var other_addrlen: posix.socklen_t = @sizeOf(posix.sockaddr);
var buf: [1024]u8 = undefined;
print("Listen on {f}\n", .{addr});
// we did not set the NONBLOCK flag (socket type flag),
// so the program will wait until data is received
const n_recv = try posix.recvfrom(
sock,
buf[0..],
0,
&other_addr,
&other_addrlen,
);
print(
"received {d} byte(s) from {any};\n string: {s}\n",
.{ n_recv, other_addr, buf[0..n_recv] },
);
// we could extract the source address of the received data by
// parsing the other_addr.data field
const n_sent = try posix.sendto(
sock,
buf[0..n_recv],
0,
&other_addr,
other_addrlen,
);
print("echoed {d} byte(s) back\n", .{n_sent});
}
启动程序后,使用 nc 进行如下测试,使用 -u 标志表示 UDP:
echo "hello zig" | nc -u localhost <port>