- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在尝试在同一台机器上使用我自己的自定义协议(protocol) ID 通过 PF_SOCKET
发送和接收类型为 SOCK_RAW
的数据包。这是我的发送方和接收方示例代码-
发件人.c
#include<sys/socket.h>
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<linux/if_arp.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CUSTOM_PROTO 0xB588
int main ()
{
int sockfd = -1;
struct sockaddr_ll dest_addr = {0}, src_addr={0};
char *buffer = NULL;
struct ethhdr *eh;
sockfd = socket(PF_PACKET, SOCK_RAW, htons(CUSTOM_PROTO) );
if ( sockfd == -1 )
{
perror("socket");
return -1;
}
buffer = malloc(1518);
eh = (struct ethhdr *)buffer;
dest_addr.sll_ifindex = if_nametoindex("eth0");
dest_addr.sll_addr[0] = 0x0;
dest_addr.sll_addr[1] = 0xc;
dest_addr.sll_addr[2] = 0x29;
dest_addr.sll_addr[3] = 0x49;
dest_addr.sll_addr[4] = 0x3f;
dest_addr.sll_addr[5] = 0x5b;
dest_addr.sll_addr[6] = 0x0;
dest_addr.sll_addr[7] = 0x0;
//other host MAC address
unsigned char dest_mac[6] = {0x0, 0xc, 0x29, 0x49, 0x3f, 0x5b};
/*set the frame header*/
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
memcpy((void*)(buffer+ETH_ALEN), (void*)dest_mac, ETH_ALEN);
eh->h_proto = htons(PAVAN_PROTO);
memcpy((void*)(buffer+ETH_ALEN+ETH_ALEN + 2), "Pavan", 6 );
int send = sendto(sockfd, buffer, 1514, 0, (struct sockaddr*)&dest_addr,
sizeof(dest_addr) );
if ( send == -1 )
{
perror("sendto");
return -1;
}
return 0;
}
接收器.c
#include<sys/socket.h>
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<linux/if_arp.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CUSTOM_PROTO 0xB588
int main ()
{
int sockfd = -1;
struct sockaddr_ll dest_addr = {0}, src_addr={0};
char *recvbuf = malloc(1514);
sockfd = socket(PF_PACKET, SOCK_RAW, htons(CUSTOM_PROTO) );
if ( sockfd == -1 )
{
perror("socket");
return -1;
}
int len = recvfrom(sockfd, recvbuf, 1514, 0, NULL, NULL);
printf("I received: \n");
return 0;
}
发送方和接收方都在 Ubuntu Virtualbox 上运行。问题是接收器在 recvfrom
中挂起。但是在 receiver.c
中,如果我将 htons(CUSTOM_PROTO)
更改为 htons(ETH_P_ALL)
,接收器工作正常。
为什么内核没有将带有我的自定义协议(protocol) ID 的数据包传送到我的自定义协议(protocol) ID 套接字?
当我使用 htons(ETH_P_ALL)
接收数据包时,我在 GDB 中验证了以太网 header 的格式是否正确
更新:如果我选择本地环回 lo
和 00 的 MAC 地址,而不是接口(interface)
,eth0
及其对应的 MAC :00:00:00:00:00CUSTOM_PROTO
工作正常!
更新 2 如果发送方和接收方在不同的机器上,CUSTOM_PROTO
工作正常。这个发现和上一个更新让我怀疑在 eth0
上发送的数据包没有被同一台机器接收。但 ETH_P_ALL
在同一台机器上运行的事实驳斥了我的怀疑。
最佳答案
ETH_P_ALL
协议(protocol)具有捕获传出数据包的特殊作用。
具有任何不等于 ETH_P_ALL
的协议(protocol)的接收器套接字接收来自设备驱动程序的该协议(protocol)的数据包。
协议(protocol)为 ETH_P_ALL
的套接字在将传出数据包发送到设备驱动程序之前接收所有数据包,并接收从设备驱动程序接收的所有传入数据包。
发送到环回设备的数据包从该设备发出,然后从设备接收到与传入相同的数据包。因此,当 CUSTOM_PROTO
与环回一起使用时,套接字将使用自定义协议(protocol)捕获数据包作为传入。
请注意,如果 ETH_P_ALL
与环回设备一起使用,每个数据包将被接收两次。一次被捕获为传出,第二次被捕获为传入。
在 eth0
的情况下,数据包从设备传输。因此,此类数据包进入设备驱动程序,然后可以在物理以太网端口的另一侧看到它们。例如,使用 VirtualBox“Host-only”网络适配器,这些数据包可以被主机系统中的一些嗅探器捕获。
但是,传输到物理端口(或其仿真端口)的数据包不会重定向回该端口。因此,它们不会作为来自设备的传入接收。这就是为什么此类数据包只能在传出方向被 ETH_P_ALL
捕获,而在传入方向无法被 CUSTOM_PROTO
捕获。
从技术上讲,应该可以准备特殊的设置来进行外部数据包环回(来自设备端口的数据包应该被发送回该端口)。在那种情况下,行为应该类似于环回设备。
查看内核文件net/core/dev.c
.有两个不同的列表:
struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly;
struct list_head ptype_all __read_mostly; /* Taps */
ptype_all
列表用于协议(protocol)为 ETH_P_ALL
的套接字处理程序。列表 ptype_base
适用于具有正常协议(protocol)的处理程序。
xmit_one()
中有一个用于传出数据包的钩子(Hook)从 dev_hard_start_xmit()
调用:
if (!list_empty(&ptype_all))
dev_queue_xmit_nit(skb, dev);
对于传出数据包,函数 dev_queue_xmit_nit()
被调用用于 ETH_P_ALL
处理 ptype_all
的每个项目。最后,类型为 AF_SOCKET
且协议(protocol)为 ETH_P_ALL
的套接字捕获该传出数据包。
因此,观察到的行为与任何自定义协议(protocol)无关。使用 ETH_P_IP
可以观察到相同的行为。在这种情况下,接收方能够捕获所有传入的 IP 数据包,但是它无法捕获从 "eth0"
发送到 的 MAC 地址的
设备。sender.c
的 IP 数据包>“eth0”
也可以通过tcpdump
看到。如果调用 tcpdump
并带有仅捕获传入数据包的选项,则不会捕获发送方发送的数据包(不同版本的 tcpdump
使用不同的命令行参数来启用此类过滤) .
在同一台机器上需要通过协议(protocol) ID 区分数据包的初始任务可以使用 ETH_P_ALL
来解决。接收方应捕获所有数据包并检查协议(protocol),例如:
while (1) {
int len = recvfrom(sockfd, recvbuf, 1514, 0, NULL, NULL);
if (ntohs(*(uint16_t*)(recvbuf + ETH_ALEN + ETH_ALEN)) == CUSTOM_PROTO) {
printf("I received: \n");
break;
}
}
有用的引用 "kernel_flow"有一个漂亮的图表 http://www.linuxfoundation.org/images/1/1c/Network_data_flow_through_kernel.png
它基于 2.6.20 内核,但是在现代内核中 ETH_P_ALL
以相同的方式处理。
关于c - 数据包套接字未接收自定义协议(protocol) ID 的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33484762/
我有一个存储结构向量的应用程序。这些结构保存有关系统上每个 GPU 的信息,如内存和 giga-flop/s。每个系统上有不同数量的 GPU。 我有一个程序可以同时在多台机器上运行,我需要收集这些数据
我很好奇 MPI 中缺少此功能: MPI_Isendrecv( ... ); 即,非阻塞发送和接收,谁能告诉我其省略背后的基本原理? 最佳答案 我的看法是 MPI_SENDRECV存在是为了方便那些想
当我用以下方法监听TCP或UDP套接字时 ssize_t recv(int sockfd, void *buf, size_t len, int flags); 或者 ssize_t recvfrom
SUM:如何在 azure 事件网格中推迟事件触发或事件接收? 我设计的系统需要对低频对象状态(创建、启动、检查长时间启动状态、结束)使用react。它看起来像是事件处理的候选者。我想用azure函数
我正在 MPI 中实现一个程序,其中主进程(等级 = 0)应该能够接收来自其他进程的请求,这些进程要求只有根才知道的变量值。如果我按等级 0 进行 MPI_Recv(...),我必须指定向根发送请求的
我正在学习DX12,并在此过程中学习“旧版Win32”。 我在退出主循环时遇到问题,这似乎与我没有收到WM_CLOSE消息有关。 在C++,Windows 10控制台应用程序中。 #include
SUM:如何在 azure 事件网格中推迟事件触发或事件接收? 我设计的系统需要对低频对象状态(创建、启动、检查长时间启动状态、结束)使用react。它看起来像是事件处理的候选者。我想用azure函数
我想编写方法来通过号码发送短信并使用编辑文本字段中的文本。发送消息后,我想收到一些声音或其他东西来提醒我收到短信。我怎样才能做到这一点?先感谢您,狼。 最佳答案 这个网站似乎对两者都有很好的描述:ht
所以我正在用 Java 编写一个程序,在 DatagramSocket 和 DatagramPacket 的帮助下发送和接收数据。问题是,在我发送数据/接收数据之间的某个时间 - 我发送数据的程序中的
我是 Android 编程新手,我正在用 Java 编写一个应用程序,该应用程序可以打开相机拍照并保存。我通过 Intents 做到了,但看不到 onActivityResult 正在运行。 我已经在
我有一个套接字服务器和一个套接字客户端。客户端只有一个套接字。我必须使用线程在客户端发送/接收数据。 static int sock = -1; static std::mutex mutex; vo
我正在尝试使用 c 中的套接字实现 TCP 服务器/客户端。我以这样的方式编写程序,即我们在客户端发送的任何内容都逐行显示在服务器中,直到键入退出。该程序可以运行,但数据最后一起显示在服务器中。有人可
我正在使用微 Controller 与 SIM808 模块通信,我想发送和接收 AT 命令。 现在的问题是,对于某些命令,我只收到了我应该收到的答案的一部分,但对于其他一些命令,我收到了我应该
我用c设计了一个消息传递接口(interface),用于在我的系统中运行的不同进程之间提供通信。该接口(interface)为此目的创建 10-12 个线程,并使用 TCP 套接字提供通信。 它工作正
我需要澄清一下在套接字程序中使用多个发送/接收。我的客户端程序如下所示(使用 TCP SOCK_STREAM)。 send(sockfd,"Messgfromlient",15,0);
我正在构建一个真正的基本代理服务器到我现有的HTTP服务器中。将传入连接添加到队列中,并将信号发送到另一个等待线程队列中的一个线程。此线程从队列中获取传入连接并对其进行处理。 问题是代理程序真的很慢。
我正在使用 $routeProvider 设置一条类似 的路线 when('/grab/:param1/:param2', { controller: 'someController',
我在欧洲有通过 HLS 流式传输的商业流媒体服务器。http://europe.server/stream1/index.m3u8现在我在美国的客户由于距离而遇到一些网络问题。 所以我在美国部署了新服
我有一个长期运行的 celery 任务,该任务遍历一系列项目并执行一些操作。 任务应该以某种方式报告当前正在处理的项目,以便最终用户知道任务的进度。 目前,我的django应用程序和celery一起坐
我需要将音频文件从浏览器发送到 python Controller 。我是这样做的: var xmlHttp = new XMLHttpRequest(); xmlHttp.open( "POST",
我是一名优秀的程序员,十分优秀!