Linux 用于在 Linux board 和每个节点之间进行通信的用户空间代码 运行 contiki udp 发送器示例代码
Linux userspace code to communicate between Linux board and each node running contiki udp sender example code
我正在使用 Contiki 创建一个涉及多个基于 STM32L152 的节点和一个 Linux 板的物联网产品。我有一个嵌入式 Linux 板(基于 iMX6),它从节点接收数据,使用蜂窝和 10 个感知不同环境参数并传送到 Linux 板的节点发送到互联网。 Linux板子有一个协处理器,运行border/edge路由器代码,协处理器的UART2线连接到Linux板子。我使用 Contiki 工具 tunslip6 创建 tun0 接口,我能够 ping 每个节点。
为了让问题更容易理解,我将解释我执行的硬件设置和步骤。
我是 运行 UDP 发送器示例代码 (STM32CubeExpansion_SUBG1_V3.0.0/Projects/Multi/Applications/Contiki/Udp-sender) 在具有 x-nucleo-ids01a5 (SPSGRF) 的 STM32L152RE-NUCLEO 板上-915 模块)电路板位于顶部。
第二个类似的硬件设置,我是运行边界路由器示例代码。 USB 数据线连接到我的 Linux 盒子。
这样做之后; sudo ./tunslip6 –s /dev/ttyACM0 aaaa::1/64
,我可以在网页上看到所有邻居节点,我也可以ping6每个节点。
我想在Linux上编写应用程序代码来接收和发送数据到每个节点,我卡在了这一点。
sudo ./tunslip6 -s /dev/ttyACM0 aaaa::1/64
********SLIP started on ``/dev/ttyACM0''
opened tun device ``/dev/tun0''
ifconfig tun0 inet `hostname` mtu 1500 up
ifconfig tun0 add aaaa::1/64
ifconfig tun0 add fe80::0:0:0:1/64
ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-
00-00-00-00-00
inet addr:127.0.1.1 P-t-P:127.0.1.1 Mask:255.255.255.255
inet6 addr: fe80::1/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
inet6 addr: fe80::8fad:d1a:c8d0:b76f/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
*** Address:aaaa::1 => aaaa:0000:0000:0000
Got configuration message of type P
Setting prefix aaaa::
Server IPv6 addresses:
aaaa::900:f4ff:c3a:f3c5
fe80::900:f4ff:c3a:f3c5
ifconfig
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:127.0.1.1 P-t-P:127.0.1.1 Mask:255.255.255.255
inet6 addr: fe80::1/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
inet6 addr: fe80::8fad:d1a:c8d0:b76f/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:67 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:3422 (3.4 KB) TX bytes:5653 (5.6 KB)
ip addr show tun0
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 127.0.1.1/32 scope host tun0
valid_lft forever preferred_lft forever
inet6 aaaa::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::1/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::8fad:d1a:c8d0:b76f/64 scope link flags 800
valid_lft forever preferred_lft forever
sudo ip -6 route
aaaa::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
This is what I am seeing on the webpage, I have one neighbor node 我可以 ping 这个。
ping6 aaaa::fdff:d2fa:2d05
PING aaaa::fdff:d2fa:2d05(aaaa::fdff:d2fa:2d05) 56 data bytes
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=1 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=2 ttl=63 time=131 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=3 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=4 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=6 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=7 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=8 ttl=63 time=131 ms
^C
--- aaaa::fdff:d2fa:2d05 ping statistics ---
8 packets transmitted, 7 received, 12% packet loss, time 7040ms
rtt min/avg/max/mdev = 130.681/131.068/131.863/0.555 ms
我不是网络和套接字编程方面的专家,我写了一些我在互联网上找到并尝试过的代码。我试过这样的事情;
import socket
UDP_IP = "aaaa::fdff:d2fa:2d05"
UDP_PORT = 1234
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) # UDP
sock.connect((UDP_IP, UDP_PORT))
while True:
data = sock.recv(1024)
print 'Received', repr(data)
问题:在Linux用户space中,同事想写一个应用程序代码,可以读写每个节点(本例aaaa::fdff:d2fa:2d05
),如何实现那?在微控制器板上,我可以用两个节点读写,但在 Linux space 中不行。请帮助我,如何从Linux用户space读取和写入数据到每个节点?如果可能,请分享一些示例代码。谢谢!
更新 - 我尝试使用不同的 Contiki 示例 contiki/examples/ipv6/rpl-udp/udp-client.c 在 Linux 主机和节点之间进行通信并取得了成功,我能够从节点接收数据。我的 python 代码是;
import socket, struct
UDP_LOCAL_IP = 'aaaa::1'
UDP_LOCAL_PORT = 5678
UDP_REMOTE_IP = 'fe80::fdff:d2fa:2d05'
UDP_REMOTE_PORT = 8765
try:
socket_rx = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
socket_rx.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
socket_rx.bind((UDP_LOCAL_IP, UDP_LOCAL_PORT))
except Exception:
print "ERROR: Server Port Binding Failed"
print 'UDP server ready: %s'% UDP_LOCAL_PORT
print
while True:
data, addr = socket_rx.recvfrom(1024)
print "address : ", addr
print "received message: ", data
print "\n"
socket_rx.sendto("Hello from serevr\n", (UDP_REMOTE_IP, UDP_REMOTE_PORT))
以上 python 代码有效。
边界路由器有一个硬编码的 IPv6 地址,根据 https://anrg.usc.edu/contiki/index.php/RPL_Border_Router 这个地址是 fe80:0000:0000:0000:0212:7401:0001:0101
(可能 运行 ip addr show tun0
-> 你的编辑显示分配的地址是 fe80:0000:0000:0000:8fad:d1a:c8d0:b76f
)。您将应用程序的套接字绑定到该地址,python 中没有相关代码。因为你使用 tunslip
你也可以使用 准确的端口 和 ipv4 协议
绑定到 localhost
为了测试,您可以使用 netcat
将 UDP 数据包直接发送到节点 ( http://www.tutorialspoint.com/unix_commands/nc.htm )
要消除错误(评论),您必须应用 inet_pton
转换 IPv6 地址(http://man7.org/linux/man-pages/man3/inet_pton.3.html)
以下是您可以转换为 python 的工作 C 代码。是为使用 Raven USB 记忆棒作为边界路由器而编写的(搜索 Contiki Jackdaw,未使用 tunslip)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <net/if.h>
int fd = 0; //socket file descriptor
struct sockaddr_in6 server;
/* ipv6 address to in6_addr structure */
const char *ip6str = "fe80::8fad:d1a:c8d0:b76f";
struct in6_addr ravenipv6;
if (inet_pton(AF_INET6, ip6str, &ravenipv6) == 1) // successful
{
printf("%s \n", "ipv6 address ...");
}
/* Create an empty IPv6 socket interface specification */
memset(&server, 0, sizeof(server));
server.sin6_family = AF_INET6;
server.sin6_flowinfo = 0;
server.sin6_port = htons(1234); // port
server.sin6_addr = ravenipv6; <- here the address converted with inet_ptons is inserted
server.sin6_scope_id = if_nametoindex("tun0"); // if your border router is on tun0
/*create socket*/
if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
printf("%s \n", "failed to create socket");
}
/*bind to socket*/
if(bind(fd, (struct sockaddr_in6*)&server, sizeof(server)) == -1)
{
printf("%s \n", "no binding ! ");
}
我正在使用 Contiki 创建一个涉及多个基于 STM32L152 的节点和一个 Linux 板的物联网产品。我有一个嵌入式 Linux 板(基于 iMX6),它从节点接收数据,使用蜂窝和 10 个感知不同环境参数并传送到 Linux 板的节点发送到互联网。 Linux板子有一个协处理器,运行border/edge路由器代码,协处理器的UART2线连接到Linux板子。我使用 Contiki 工具 tunslip6 创建 tun0 接口,我能够 ping 每个节点。 为了让问题更容易理解,我将解释我执行的硬件设置和步骤。
我是 运行 UDP 发送器示例代码 (STM32CubeExpansion_SUBG1_V3.0.0/Projects/Multi/Applications/Contiki/Udp-sender) 在具有 x-nucleo-ids01a5 (SPSGRF) 的 STM32L152RE-NUCLEO 板上-915 模块)电路板位于顶部。
第二个类似的硬件设置,我是运行边界路由器示例代码。 USB 数据线连接到我的 Linux 盒子。
这样做之后; sudo ./tunslip6 –s /dev/ttyACM0 aaaa::1/64
,我可以在网页上看到所有邻居节点,我也可以ping6每个节点。
我想在Linux上编写应用程序代码来接收和发送数据到每个节点,我卡在了这一点。
sudo ./tunslip6 -s /dev/ttyACM0 aaaa::1/64
********SLIP started on ``/dev/ttyACM0''
opened tun device ``/dev/tun0''
ifconfig tun0 inet `hostname` mtu 1500 up
ifconfig tun0 add aaaa::1/64
ifconfig tun0 add fe80::0:0:0:1/64
ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-
00-00-00-00-00
inet addr:127.0.1.1 P-t-P:127.0.1.1 Mask:255.255.255.255
inet6 addr: fe80::1/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
inet6 addr: fe80::8fad:d1a:c8d0:b76f/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
*** Address:aaaa::1 => aaaa:0000:0000:0000
Got configuration message of type P
Setting prefix aaaa::
Server IPv6 addresses:
aaaa::900:f4ff:c3a:f3c5
fe80::900:f4ff:c3a:f3c5
ifconfig
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:127.0.1.1 P-t-P:127.0.1.1 Mask:255.255.255.255
inet6 addr: fe80::1/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
inet6 addr: fe80::8fad:d1a:c8d0:b76f/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:67 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:3422 (3.4 KB) TX bytes:5653 (5.6 KB)
ip addr show tun0
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 127.0.1.1/32 scope host tun0
valid_lft forever preferred_lft forever
inet6 aaaa::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::1/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::8fad:d1a:c8d0:b76f/64 scope link flags 800
valid_lft forever preferred_lft forever
sudo ip -6 route
aaaa::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
This is what I am seeing on the webpage, I have one neighbor node 我可以 ping 这个。
ping6 aaaa::fdff:d2fa:2d05
PING aaaa::fdff:d2fa:2d05(aaaa::fdff:d2fa:2d05) 56 data bytes
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=1 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=2 ttl=63 time=131 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=3 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=4 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=6 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=7 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=8 ttl=63 time=131 ms
^C
--- aaaa::fdff:d2fa:2d05 ping statistics ---
8 packets transmitted, 7 received, 12% packet loss, time 7040ms
rtt min/avg/max/mdev = 130.681/131.068/131.863/0.555 ms
我不是网络和套接字编程方面的专家,我写了一些我在互联网上找到并尝试过的代码。我试过这样的事情;
import socket
UDP_IP = "aaaa::fdff:d2fa:2d05"
UDP_PORT = 1234
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) # UDP
sock.connect((UDP_IP, UDP_PORT))
while True:
data = sock.recv(1024)
print 'Received', repr(data)
问题:在Linux用户space中,同事想写一个应用程序代码,可以读写每个节点(本例aaaa::fdff:d2fa:2d05
),如何实现那?在微控制器板上,我可以用两个节点读写,但在 Linux space 中不行。请帮助我,如何从Linux用户space读取和写入数据到每个节点?如果可能,请分享一些示例代码。谢谢!
更新 - 我尝试使用不同的 Contiki 示例 contiki/examples/ipv6/rpl-udp/udp-client.c 在 Linux 主机和节点之间进行通信并取得了成功,我能够从节点接收数据。我的 python 代码是;
import socket, struct
UDP_LOCAL_IP = 'aaaa::1'
UDP_LOCAL_PORT = 5678
UDP_REMOTE_IP = 'fe80::fdff:d2fa:2d05'
UDP_REMOTE_PORT = 8765
try:
socket_rx = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
socket_rx.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
socket_rx.bind((UDP_LOCAL_IP, UDP_LOCAL_PORT))
except Exception:
print "ERROR: Server Port Binding Failed"
print 'UDP server ready: %s'% UDP_LOCAL_PORT
print
while True:
data, addr = socket_rx.recvfrom(1024)
print "address : ", addr
print "received message: ", data
print "\n"
socket_rx.sendto("Hello from serevr\n", (UDP_REMOTE_IP, UDP_REMOTE_PORT))
以上 python 代码有效。
边界路由器有一个硬编码的 IPv6 地址,根据 https://anrg.usc.edu/contiki/index.php/RPL_Border_Router 这个地址是 fe80:0000:0000:0000:0212:7401:0001:0101
(可能 运行 ip addr show tun0
-> 你的编辑显示分配的地址是 fe80:0000:0000:0000:8fad:d1a:c8d0:b76f
)。您将应用程序的套接字绑定到该地址,python 中没有相关代码。因为你使用 tunslip
你也可以使用 准确的端口 和 ipv4 协议
为了测试,您可以使用 netcat
将 UDP 数据包直接发送到节点 ( http://www.tutorialspoint.com/unix_commands/nc.htm )
要消除错误(评论),您必须应用 inet_pton
转换 IPv6 地址(http://man7.org/linux/man-pages/man3/inet_pton.3.html)
以下是您可以转换为 python 的工作 C 代码。是为使用 Raven USB 记忆棒作为边界路由器而编写的(搜索 Contiki Jackdaw,未使用 tunslip)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <net/if.h>
int fd = 0; //socket file descriptor
struct sockaddr_in6 server;
/* ipv6 address to in6_addr structure */
const char *ip6str = "fe80::8fad:d1a:c8d0:b76f";
struct in6_addr ravenipv6;
if (inet_pton(AF_INET6, ip6str, &ravenipv6) == 1) // successful
{
printf("%s \n", "ipv6 address ...");
}
/* Create an empty IPv6 socket interface specification */
memset(&server, 0, sizeof(server));
server.sin6_family = AF_INET6;
server.sin6_flowinfo = 0;
server.sin6_port = htons(1234); // port
server.sin6_addr = ravenipv6; <- here the address converted with inet_ptons is inserted
server.sin6_scope_id = if_nametoindex("tun0"); // if your border router is on tun0
/*create socket*/
if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
printf("%s \n", "failed to create socket");
}
/*bind to socket*/
if(bind(fd, (struct sockaddr_in6*)&server, sizeof(server)) == -1)
{
printf("%s \n", "no binding ! ");
}