-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples/sock_tcp_echo: add TCP echo client / server
- Loading branch information
Showing
4 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# name of your application | ||
APPLICATION = sock_tcp_echo | ||
|
||
# If no BOARD is found in the environment, use this default: | ||
BOARD ?= native | ||
|
||
# default to using GNRC | ||
LWIP ?= 0 | ||
|
||
# This has to be the absolute path to the RIOT base directory: | ||
RIOTBASE ?= $(CURDIR)/../.. | ||
|
||
USEMODULE += sock_tcp | ||
USEMODULE += netdev_default | ||
|
||
USEMODULE += shell | ||
USEMODULE += shell_commands | ||
USEMODULE += ps | ||
USEMODULE += netutils | ||
|
||
ifeq (1, $(LWIP)) | ||
USEMODULE += ipv6_addr | ||
USEMODULE += lwip_ipv6_autoconfig | ||
USEMODULE += lwip_netdev | ||
else | ||
USEMODULE += auto_init_gnrc_netif | ||
USEMODULE += gnrc_ipv6_default | ||
# we want to be able to open two sockets | ||
CFLAGS += -DCONFIG_GNRC_TCP_RCV_BUFFERS=2 | ||
endif | ||
|
||
# Comment this out to disable code in RIOT that does safety checking | ||
# which is not needed in a production environment but helps in the | ||
# development process: | ||
DEVELHELP ?= 1 | ||
|
||
# As there is a .config we want to explicitly disable Kconfig by setting | ||
# the variable to empty | ||
SHOULD_RUN_KCONFIG ?= | ||
|
||
include $(RIOTBASE)/Makefile.include |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
BOARD_INSUFFICIENT_MEMORY := \ | ||
arduino-duemilanove \ | ||
arduino-leonardo \ | ||
arduino-mega2560 \ | ||
arduino-nano \ | ||
arduino-uno \ | ||
atmega328p \ | ||
atmega328p-xplained-mini \ | ||
atxmega-a1u-xpro \ | ||
bluepill-stm32f030c8 \ | ||
i-nucleo-lrwan1 \ | ||
msb-430 \ | ||
msb-430h \ | ||
nucleo-f030r8 \ | ||
nucleo-f031k6 \ | ||
nucleo-f042k6 \ | ||
nucleo-f303k8 \ | ||
nucleo-f334r8 \ | ||
nucleo-l011k4 \ | ||
nucleo-l031k6 \ | ||
nucleo-l053r8 \ | ||
samd10-xmini \ | ||
slstk3400a \ | ||
stk3200 \ | ||
stm32f030f4-demo \ | ||
stm32f0discovery \ | ||
stm32l0538-disco \ | ||
telosb \ | ||
waspmote-pro \ | ||
z1 \ | ||
# |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
TCP Echo Server / Client | ||
======================== | ||
|
||
This is a simple TCP echo server / client that uses the SOCK API. | ||
It can make use of both the GNRC and the LWIP network stack. | ||
The default is GNRC, to chose LWIP set `LWIP=1` when compiling the example. | ||
|
||
## Echo Server | ||
|
||
The echo server will echo back any data that it receives. | ||
To start the echo server on port 12345 run | ||
|
||
listen 12345 | ||
|
||
## Echo Client | ||
|
||
The echo client will connect to a server, send some data and wait for the reply. | ||
To send data with the echo client to a server running on 2001:db8::1 run | ||
|
||
send 2001:db8::1 12345 some data |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
/* | ||
* Copyright (C) 2016 Freie Universität Berlin | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @{ | ||
* | ||
* @file | ||
* @author Martine Lenders <m.lenders@fu-berlin.de> | ||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com> | ||
*/ | ||
|
||
#include <stdio.h> | ||
|
||
#include "net/sock/tcp.h" | ||
#include "net/ipv6/addr.h" | ||
#include "net/utils.h" | ||
#include "shell.h" | ||
|
||
#define SOCK_QUEUE_LEN 1 | ||
|
||
static char _echo_server_stack[THREAD_STACKSIZE_DEFAULT]; | ||
|
||
static int _cmd_tcp_send(int argc, char **argv) | ||
{ | ||
int res; | ||
sock_tcp_t sock; | ||
sock_tcp_ep_t remote; | ||
netif_t *netif; | ||
char buf[128]; | ||
|
||
if (argc < 4) { | ||
printf("usage: %s <addr> <port> <data>\n", argv[0]); | ||
return -1; | ||
} | ||
|
||
if (netutils_get_ipv6((ipv6_addr_t *)&remote.addr, | ||
&netif, argv[1]) < 0) { | ||
printf("can't resolve %s\n", argv[1]); | ||
return -1; | ||
} | ||
|
||
remote.family = AF_INET6; | ||
remote.netif = netif ? netif_get_id(netif) : 0; | ||
remote.port = atoi(argv[2]); | ||
|
||
if (remote.port == 0) { | ||
printf("Invalid port: %s\n", argv[2]); | ||
return -1; | ||
} | ||
|
||
if ((res = sock_tcp_connect(&sock, &remote, 0, 0)) < 0) { | ||
printf("Error connecting sock: %s\n", strerror(-res)); | ||
return -1; | ||
} | ||
|
||
if ((res = sock_tcp_write(&sock, argv[3], strlen(argv[3]))) < 0) { | ||
printf("Errored on write: %s\n", strerror(-res)); | ||
goto error; | ||
} | ||
|
||
if ((res = sock_tcp_read(&sock, &buf, sizeof(buf), SOCK_NO_TIMEOUT)) <= 0) { | ||
printf("Disconnected: %s\n", strerror(-res)); | ||
goto error; | ||
} | ||
|
||
buf[res] = 0; | ||
printf("Read: \"%s\"\n", buf); | ||
|
||
error: | ||
sock_tcp_disconnect(&sock); | ||
|
||
return 0; | ||
} | ||
SHELL_COMMAND(send, "send data over TCP", _cmd_tcp_send); | ||
|
||
static void *_run_echo_server(void *ctx) | ||
{ | ||
sock_tcp_t sock_queue[SOCK_QUEUE_LEN]; | ||
char buf[128]; | ||
uint16_t port = (uintptr_t)ctx; | ||
|
||
sock_tcp_ep_t local = SOCK_IPV6_EP_ANY; | ||
sock_tcp_queue_t queue; | ||
local.port = port; | ||
if (sock_tcp_listen(&queue, &local, sock_queue, SOCK_QUEUE_LEN, 0) < 0) { | ||
puts("Error creating listening queue"); | ||
return NULL; | ||
} | ||
printf("Listening on port %u\n", port); | ||
while (1) { | ||
sock_tcp_t *sock; | ||
if (sock_tcp_accept(&queue, &sock, SOCK_NO_TIMEOUT) < 0) { | ||
puts("Error accepting new sock"); | ||
break; | ||
} | ||
|
||
int res = 0; | ||
puts("Reading data"); | ||
while (res >= 0) { | ||
res = sock_tcp_read(sock, &buf, sizeof(buf), SOCK_NO_TIMEOUT); | ||
if (res <= 0) { | ||
printf("Disconnected: %s\n", strerror(-res)); | ||
break; | ||
} | ||
buf[res] = 0; | ||
printf("Read: \"%s\"\n", buf); | ||
if ((res = sock_tcp_write(sock, &buf, res)) < 0) { | ||
printf("Errored on write: %s\n", strerror(-res)); | ||
} | ||
} | ||
sock_tcp_disconnect(sock); | ||
} | ||
sock_tcp_stop_listen(&queue); | ||
return NULL; | ||
} | ||
|
||
static int _cmd_tcp_listen(int argc, char **argv) | ||
{ | ||
static kernel_pid_t pid; | ||
uint16_t port; | ||
|
||
if (argc < 2) { | ||
printf("usage: %s <port>\n", argv[0]); | ||
return -1; | ||
} | ||
|
||
if (pid) { | ||
puts("server already running"); | ||
return -1; | ||
} | ||
|
||
port = atoi(argv[1]); | ||
|
||
if (port == 0) { | ||
printf("invalid port: %s\n", argv[1]); | ||
return -1; | ||
} | ||
|
||
pid = thread_create(_echo_server_stack, sizeof(_echo_server_stack), | ||
THREAD_PRIORITY_MAIN - 1, 0, | ||
_run_echo_server, (void*)(uintptr_t)port, "echo_server"); | ||
return 0; | ||
} | ||
SHELL_COMMAND(listen, "start echo server", _cmd_tcp_listen); | ||
|
||
int main(void) | ||
{ | ||
puts("RIOT TCP client example application"); | ||
|
||
/* start shell */ | ||
puts("All up, running the shell now"); | ||
char line_buf[SHELL_DEFAULT_BUFSIZE]; | ||
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); | ||
|
||
/* should be never reached */ | ||
return 0; | ||
} | ||
/** @} */ |