Commit 9416a3d4 authored by Florian Fischer's avatar Florian Fischer
Browse files

[go/tokio] set SO_REUSE{ADDR,PORT} sockopts

And format both.
parent 96f291b7
Pipeline #72965 passed with stage
in 2 minutes and 1 second
package main
import (
"context"
"flag"
"log"
"net"
"os"
"strconv"
"syscall"
"time"
)
// Taken from https://pkg.go.dev/golang.org/x/sys/unix#pkg-constants
const (
SOL_SOCKET = 0x1
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
)
func main() {
port := flag.Int("port", 12345, "Port to accept connections on.")
host := flag.String("host", "0.0.0.0", "Host or IP to bind to")
computation := flag.Uint("computation", 0, "Computation done before sending a responce in microseconds")
flag.Parse()
l, err := net.Listen("tcp", *host+":"+strconv.Itoa(*port))
lc := net.ListenConfig{
Control: func(network, address string, conn syscall.RawConn) error {
var operr error
err := conn.Control(func(fd uintptr) {
operr = syscall.SetsockoptInt(int(fd), SOL_SOCKET, SO_REUSEADDR, 1)
if operr != nil {
return
}
operr = syscall.SetsockoptInt(int(fd), SOL_SOCKET, SO_REUSEPORT, 1)
})
if err != nil {
return err
}
return operr
},
}
l, err := lc.Listen(context.Background(), "tcp", *host+":"+strconv.Itoa(*port))
if err != nil {
log.Panicln(err)
}
log.Println("Listening to connections at '"+*host+"' on port", strconv.Itoa(*port), "with", *computation, "microseconds computation")
defer l.Close()
......
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
......@@ -18,6 +20,12 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
......@@ -39,7 +47,7 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
]
[[package]]
......@@ -63,7 +71,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
]
[[package]]
......@@ -94,6 +102,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "net2"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
dependencies = [
"cfg-if 0.1.10",
"libc",
"winapi",
]
[[package]]
name = "ntapi"
version = "0.3.6"
......@@ -136,7 +155,7 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
dependencies = [
"cfg-if",
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
......@@ -233,6 +252,7 @@ dependencies = [
name = "tokio-echo"
version = "0.1.0"
dependencies = [
"net2",
"tokio",
]
......
......@@ -6,3 +6,4 @@ edition = "2018"
[dependencies]
tokio = { version = "1", features = ["full"] }
net2 = { version = "0.2"}
use std::env;
use std::time::{Duration, Instant};
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
extern crate net2;
use net2::{unix::UnixTcpBuilderExt, TcpBuilder};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
......@@ -11,7 +15,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
2 => args[1].parse()?,
_=> {
_ => {
let prog = &args[0];
panic!("Usage: {} [computation in us]", prog);
}
......@@ -28,43 +32,55 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
None => {}
};
runtime_builder.enable_all().build().unwrap().block_on(async {
let listener = TcpListener::bind("[::]:12345").await.unwrap();
println!("Echoserver listening on :::12345 with {} microseconds computation", computation);
runtime_builder
.enable_all()
.build()
.unwrap()
.block_on(async {
let std_listener = TcpBuilder::new_v6()?
.reuse_address(true)?
.reuse_port(true)?
.bind("[::]:12345")?
.listen(4096)?;
let listener = TcpListener::from_std(std_listener).unwrap();
println!(
"Echoserver listening on :::12345 with {} microseconds computation",
computation
);
loop {
let (mut socket, _) = listener.accept().await.unwrap();
loop {
let (mut socket, _) = listener.accept().await.unwrap();
tokio::spawn(async move {
let mut buf = [0; 1024];
tokio::spawn(async move {
let mut buf = [0; 1024];
// In a loop, read data from the socket and write the data back.
loop {
let n = match socket.read(&mut buf).await {
// socket closed
Ok(n) if n == 0 => return,
Ok(n) => n,
Err(e) => {
eprintln!("failed to read from socket; err = {:?}", e);
return;
}
};
// In a loop, read data from the socket and write the data back.
loop {
let n = match socket.read(&mut buf).await {
// socket closed
Ok(n) if n == 0 => return,
Ok(n) => n,
Err(e) => {
eprintln!("failed to read from socket; err = {:?}", e);
return;
}
};
if n == 5 && &buf[0..n] == "quit\n".as_bytes() {
std::process::exit(0);
}
if n == 5 && &buf[0..n] == "quit\n".as_bytes() {
std::process::exit(0);
}
let now = Instant::now();
let execution_duartion = Duration::from_micros(computation);
while now.elapsed() < execution_duartion {}
let now = Instant::now();
let execution_duartion = Duration::from_micros(computation);
while now.elapsed() < execution_duartion {}
// Write the data back
if let Err(e) = socket.write_all(&buf[0..n]).await {
eprintln!("failed to write to socket; err = {:?}", e);
return;
// Write the data back
if let Err(e) = socket.write_all(&buf[0..n]).await {
eprintln!("failed to write to socket; err = {:?}", e);
return;
}
}
}
});
}
})
});
}
})
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment