Add echo server
This commit is contained in:
parent
167f55ba13
commit
ed42636739
8 changed files with 102 additions and 66 deletions
|
@ -31,6 +31,7 @@ list(APPEND CSOURCES
|
||||||
|
|
||||||
add_executable(donar ${CSOURCES} src/donar.c)
|
add_executable(donar ${CSOURCES} src/donar.c)
|
||||||
add_executable(measlat ${CSOURCES} src/meas_lat.c)
|
add_executable(measlat ${CSOURCES} src/meas_lat.c)
|
||||||
|
add_executable(udpecho ${CSOURCES} src/udp_echo.c)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_search_module(GLIB REQUIRED glib-2.0)
|
pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||||
|
@ -41,6 +42,9 @@ target_link_libraries(donar ${GLIB_LDFLAGS})
|
||||||
target_include_directories(measlat PRIVATE ${GLIB_INCLUDE_DIRS})
|
target_include_directories(measlat PRIVATE ${GLIB_INCLUDE_DIRS})
|
||||||
target_link_libraries(measlat ${GLIB_LDFLAGS})
|
target_link_libraries(measlat ${GLIB_LDFLAGS})
|
||||||
|
|
||||||
install(TARGETS donar measlat
|
target_include_directories(udpecho PRIVATE ${GLIB_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(udpecho ${GLIB_LDFLAGS})
|
||||||
|
|
||||||
|
install(TARGETS donar measlat udpecho
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION bin
|
||||||
LIBRARY DESTINATION lib)
|
LIBRARY DESTINATION lib)
|
|
@ -109,6 +109,7 @@ on_socks5_err:
|
||||||
evt_core_rm_fd (ctx, fdinfo->fd);
|
evt_core_rm_fd (ctx, fdinfo->fd);
|
||||||
sleep(2);
|
sleep(2);
|
||||||
init_tcp_client (app_ctx, pos);
|
init_tcp_client (app_ctx, pos);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo,
|
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo,
|
||||||
|
|
|
@ -26,7 +26,7 @@ void init_udp_remote(char* port, struct evt_core_ctx* evts) {
|
||||||
fdinfo.other = udp_t;
|
fdinfo.other = udp_t;
|
||||||
|
|
||||||
// 2. Duplicate sockets
|
// 2. Duplicate sockets
|
||||||
sock1 = create_udp_server (port);
|
sock1 = create_udp_server ("127.13.3.7", port);
|
||||||
if (sock1 < 0) goto socket_failed;
|
if (sock1 < 0) goto socket_failed;
|
||||||
sock2 = dup(sock1);
|
sock2 = dup(sock1);
|
||||||
if (sock2 < 0) goto socket_failed;
|
if (sock2 < 0) goto socket_failed;
|
||||||
|
|
|
@ -33,7 +33,7 @@ void init_tcp_servers(struct donar_server_ctx* ctx) {
|
||||||
int err, sock = 0;
|
int err, sock = 0;
|
||||||
for (int i = 0; i < PORT_SIZE; i++) {
|
for (int i = 0; i < PORT_SIZE; i++) {
|
||||||
sprintf (buffer, "%d", ctx->ports[i]);
|
sprintf (buffer, "%d", ctx->ports[i]);
|
||||||
sock = create_tcp_server (buffer);
|
sock = create_tcp_server ("127.13.3.7", buffer);
|
||||||
if (sock < 0) goto socket_create_err;
|
if (sock < 0) goto socket_create_err;
|
||||||
err = listen(sock, SOMAXCONN);
|
err = listen(sock, SOMAXCONN);
|
||||||
if (err != 0) goto socket_create_err;
|
if (err != 0) goto socket_create_err;
|
||||||
|
|
|
@ -51,7 +51,7 @@ int create_udp_client(char* host, char* service) {
|
||||||
return create_ip_client (host, service, SOCK_DGRAM);
|
return create_ip_client (host, service, SOCK_DGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_ip_server(char* service, int type) {
|
int create_ip_server(char* host, char* service, int type) {
|
||||||
int err, sock, enable;
|
int err, sock, enable;
|
||||||
struct addrinfo conf;
|
struct addrinfo conf;
|
||||||
struct addrinfo *result, *cursor;
|
struct addrinfo *result, *cursor;
|
||||||
|
@ -63,7 +63,7 @@ int create_ip_server(char* service, int type) {
|
||||||
conf.ai_protocol = 0;
|
conf.ai_protocol = 0;
|
||||||
|
|
||||||
enable = 1;
|
enable = 1;
|
||||||
err = getaddrinfo("127.13.3.7", service, &conf, &result);
|
err = getaddrinfo(host, service, &conf, &result);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
fprintf(stderr, "Error with getaddrinfo()\n");
|
fprintf(stderr, "Error with getaddrinfo()\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -92,12 +92,12 @@ int create_ip_server(char* service, int type) {
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_tcp_server(char* service) {
|
int create_tcp_server(char* host, char* service) {
|
||||||
return create_ip_server (service, SOCK_STREAM);
|
return create_ip_server (host, service, SOCK_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_udp_server(char* service) {
|
int create_udp_server(char* host, char* service) {
|
||||||
return create_ip_server (service, SOCK_DGRAM);
|
return create_ip_server (host, service, SOCK_DGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
|
|
||||||
int create_tcp_client(char* host, char* service);
|
int create_tcp_client(char* host, char* service);
|
||||||
int create_udp_client(char* host, char* service);
|
int create_udp_client(char* host, char* service);
|
||||||
int create_tcp_server(char* service);
|
int create_tcp_server(char* host, char* service);
|
||||||
int create_udp_server(char* service);
|
int create_udp_server(char* host, char* service);
|
||||||
int make_socket_non_blocking(int fd);
|
int make_socket_non_blocking(int fd);
|
||||||
void add_fd_to_epoll(int epollfd, int fd, uint32_t flags);
|
void add_fd_to_epoll(int epollfd, int fd, uint32_t flags);
|
||||||
int read_entity(int fd, void* entity, int size);
|
int read_entity(int fd, void* entity, int size);
|
||||||
|
|
86
src/udp_echo.c
Normal file
86
src/udp_echo.c
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "evt_core.h"
|
||||||
|
#include "net_tools.h"
|
||||||
|
|
||||||
|
int on_udp(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
||||||
|
char buffer[1500];
|
||||||
|
ssize_t nread, nwritten;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
nread = recvfrom(fdinfo->fd, buffer, sizeof(buffer), MSG_TRUNC, (struct sockaddr*)&addr, &addrlen);
|
||||||
|
if (nread == -1 && errno == EAGAIN) return 1; // Read done
|
||||||
|
if (nread <= 0 || nread > sizeof(buffer)) {
|
||||||
|
fprintf(stderr, "Message is either truncated or an error occured. nread=%ld\n", nread);
|
||||||
|
perror("read errno");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nwritten = sendto(fdinfo->fd, buffer, nread, 0, (struct sockaddr*)&addr, addrlen);
|
||||||
|
// @FIXME don't support EAGAIN on write. Could be intended, you don't think so?
|
||||||
|
if (nwritten != nread) {
|
||||||
|
fprintf(stderr, "Didn't write the same number of bytes as read. nread=%ld, nwritten=%ld\n", nread, nwritten);
|
||||||
|
perror("write errno");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
printf("~ udpecho ~\n");
|
||||||
|
|
||||||
|
int opt, udp_sock, verbose = 0;
|
||||||
|
char *port = NULL;
|
||||||
|
struct evt_core_ctx evts = {0};
|
||||||
|
|
||||||
|
// 1. Parse parameters
|
||||||
|
while ((opt = getopt(argc, argv, "p:v")) != -1) {
|
||||||
|
switch(opt) {
|
||||||
|
case 'v':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
port = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Register category
|
||||||
|
struct evt_core_cat udp_read = {
|
||||||
|
.app_ctx = NULL,
|
||||||
|
.free_app_ctx = NULL,
|
||||||
|
.cb = on_udp,
|
||||||
|
.err_cb = NULL,
|
||||||
|
.name = "udp-read",
|
||||||
|
.flags = EPOLLIN | EPOLLET,
|
||||||
|
.socklist = NULL
|
||||||
|
};
|
||||||
|
evt_core_init(&evts);
|
||||||
|
evt_core_add_cat(&evts, &udp_read);
|
||||||
|
|
||||||
|
// 3. Register UDP socket
|
||||||
|
udp_sock = create_udp_server ("127.0.0.1", port);
|
||||||
|
|
||||||
|
char url[1024];
|
||||||
|
struct evt_core_cat cat = {0};
|
||||||
|
struct evt_core_fdinfo fdinfo = {0};
|
||||||
|
fdinfo.cat = &cat;
|
||||||
|
fdinfo.url = url;
|
||||||
|
|
||||||
|
fdinfo.fd = udp_sock;
|
||||||
|
sprintf(url, "udp:rw:127.0.0.1:%s", port);
|
||||||
|
fdinfo.cat->name = "udp-read";
|
||||||
|
evt_core_add_fd(&evts, &fdinfo);
|
||||||
|
|
||||||
|
// 4. Start main loop
|
||||||
|
evt_core_loop (&evts);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
usage:
|
||||||
|
fprintf(stderr, "Usage: %s -p <port> [-v]\n", argv[0]);
|
||||||
|
}
|
55
udp-echo.py
55
udp-echo.py
|
@ -1,55 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
A simple UDP echo server.
|
|
||||||
"""
|
|
||||||
import argparse
|
|
||||||
import itertools
|
|
||||||
import logging
|
|
||||||
import socket
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# the buffer for receiving incoming messages
|
|
||||||
BUFFER_SIZE = 4096
|
|
||||||
|
|
||||||
def receive_next(sock):
|
|
||||||
"Repeatedly tries receiving on the given socket until some data comes in."
|
|
||||||
logger.debug("Waiting to receive data...")
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
return sock.recvfrom(BUFFER_SIZE)
|
|
||||||
except socket.timeout:
|
|
||||||
logger.debug("No data received yet: retrying.")
|
|
||||||
pass
|
|
||||||
|
|
||||||
def receive_and_send_one(sock):
|
|
||||||
"Waits for a single datagram over the socket and echoes it back."
|
|
||||||
input_data, addr = receive_next(sock)
|
|
||||||
print(input_data)
|
|
||||||
#message = input_data.decode()
|
|
||||||
#logger.info("Received message from %s: %s (%s bytes).", addr, message, len(input_data))
|
|
||||||
output_len = sock.sendto(input_data, addr)
|
|
||||||
#logger.info("Echoed message back to %s: %s (%s bytes).", addr, message, output_len)
|
|
||||||
|
|
||||||
def start(args):
|
|
||||||
"Runs the server."
|
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
sock.settimeout(5) # seconds
|
|
||||||
sock.bind((args.host, args.port))
|
|
||||||
logger.info("Listening on %s:%s.", args.host, args.port)
|
|
||||||
try:
|
|
||||||
for i in itertools.count(1):
|
|
||||||
receive_and_send_one(sock)
|
|
||||||
finally:
|
|
||||||
logger.info("Shutting down.")
|
|
||||||
sock.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = argparse.ArgumentParser(__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
||||||
parser.add_argument('--host', help='The host that the server socket should bind to.', default="0.0.0.0")
|
|
||||||
parser.add_argument('--port', help='The port that the server socket should bind to.', type=int, default=123)
|
|
||||||
parser.add_argument('--verbose', '-v', help="Increases the logging verbosity level.", action='count')
|
|
||||||
args = parser.parse_args()
|
|
||||||
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO,
|
|
||||||
format='%(asctime)s %(levelname)s %(message)s')
|
|
||||||
start(args)
|
|
Loading…
Reference in a new issue