Last active
May 8, 2024 08:55
-
-
Save kawakami-o3/e4b5dc28a4d63608a2c4819c85c481d3 to your computer and use it in GitHub Desktop.
recvmmsg and sendmmsg examples in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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