Skip to content

Instantly share code, notes, and snippets.

@kawakami-o3
Last active May 8, 2024 08:55
Show Gist options
  • Save kawakami-o3/e4b5dc28a4d63608a2c4819c85c481d3 to your computer and use it in GitHub Desktop.
Save kawakami-o3/e4b5dc28a4d63608a2c4819c85c481d3 to your computer and use it in GitHub Desktop.
recvmmsg and sendmmsg examples in Rust
// https://linuxjm.osdn.jp/html/LDP_man-pages/man2/recvmmsg.2.html in Rust
//
// 1. Run a receiver.
// $ cargo run
// 2. Send test data to a receiver.
// $ while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234; done
use std::mem;
use libc::*;
const VLEN: c_uint = 10;
const BUFSIZE: c_uint = 200;
const TIMEOUT: c_long = 1;
unsafe fn recv_test() {
let sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if sockfd == -1 {
panic!("socket()");
}
let sa = sockaddr_in{
sin_family: AF_INET as u16,
sin_addr: in_addr { s_addr: htonl(INADDR_LOOPBACK) },
sin_port: htons(1234),
sin_zero: [0; 8],
};
if bind(sockfd, &sa as *const _ as *const sockaddr, mem::size_of_val(&sa) as socklen_t) == -1 {
panic!("bind()");
}
let mut msgs: [mmsghdr; VLEN as usize] = [ mem::zeroed(); VLEN as usize];
let mut iovecs: [iovec; VLEN as usize] = [ mem::zeroed(); VLEN as usize];
let mut bufs: [[c_char; VLEN as usize]; (BUFSIZE+1) as usize] = [[mem::zeroed(); VLEN as usize]; (BUFSIZE+1) as usize];
for i in 0..VLEN as usize {
iovecs[i].iov_base = bufs[i].as_mut_ptr() as *mut c_void;
iovecs[i].iov_len = BUFSIZE as usize;
msgs[i].msg_hdr.msg_iov = &mut iovecs[i] as *mut _ as *mut iovec;
msgs[i].msg_hdr.msg_iovlen = 1;
}
let mut timeout = timespec {
tv_sec: TIMEOUT,
tv_nsec: 0,
};
let retval = recvmmsg(sockfd, msgs.as_mut_ptr(), VLEN, 0, &mut timeout as *mut timespec);
if retval == -1 {
panic!("recvmmsg()");
}
println!("{} messages received", retval);
for i in 0..retval as usize {
print!("{}", bufs[i].iter().map(|&s| s as u8 as char).collect::<String>());
}
}
fn htonl(n: u32) -> u32 {
n.to_be()
}
fn htons(n: u16) -> u16 {
n.to_be()
}
fn main() {
unsafe {
recv_test();
}
}
use std::mem;
use libc::*;
unsafe fn sendmmsg_run() {
let sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if sockfd == -1 {
panic!("socket()");
}
let sa = sockaddr_in{
sin_family: AF_INET as u16,
sin_addr: in_addr { s_addr: htonl(INADDR_LOOPBACK) },
sin_port: htons(1234),
sin_zero: [0; 8],
};
if connect(sockfd, &sa as *const _ as *const sockaddr, mem::size_of_val(&sa) as socklen_t) == -1 {
panic!("connect()");
}
let mut msg1: [iovec; 2] = [mem::zeroed(); 2];
let mut one = "one".to_string();
msg1[0].iov_base = one.as_mut_ptr() as *mut c_void;
msg1[0].iov_len = 3;
let mut two = "two".to_string();
msg1[1].iov_base = two.as_mut_ptr() as *mut c_void;
msg1[1].iov_len = 3;
let mut msg2: iovec = mem::zeroed();
let mut three = "three".to_string();
msg2.iov_base = three.as_mut_ptr() as *mut c_void;
msg2.iov_len = 5;
let mut msg: [mmsghdr; 2] = [mem::zeroed(); 2];
msg[0].msg_hdr.msg_iov = &mut msg1[0];
msg[0].msg_hdr.msg_iovlen = 2;
msg[1].msg_hdr.msg_iov = &mut msg2;
msg[1].msg_hdr.msg_iovlen = 1;
let retval = sendmmsg(sockfd, &mut msg[0] as *mut mmsghdr, 2, 0);
if retval == -1 {
panic!("sendmmsg()");
} else {
println!("> {}", retval);
}
}
fn htonl(n: u32) -> u32 {
n.to_be()
}
fn htons(n: u16) -> u16 {
n.to_be()
}
fn main() {
unsafe {
sendmmsg_run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment