您可以使用IP_PKTINFO获取数据包发送到的多播组的地址 - 即使套接字订阅了一堆多播组。有了这个,您将按顺序获取数据包并按组地址过滤。请参阅以下示例:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 1234

#define PPANIC(msg) perror(msg); exit(1);

#define STATS_PATCH 0

int main(int argc, char **argv)

{

fd_set master;

fd_set read_fds;

struct sockaddr_in serveraddr;

int sock;

int opt = 1;

size_t i;

int rc;

char *mcast_groups[] = {

"226.0.0.1",

"226.0.0.2",

NULL

};

#if STATS_PATCH

struct stat stat_buf;

#endif

struct ip_mreq imreq;

FD_ZERO(&master);

FD_ZERO(&read_fds);

rc = sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

if(rc == -1)

{

PPANIC("socket() failed");

}

rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

if(rc == -1)

{

PPANIC("setsockopt(reuse) failed");

}

memset(&serveraddr, 0, sizeof(serveraddr));

serveraddr.sin_family = AF_INET;

serveraddr.sin_port = htons(PORT);

serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

rc = bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));

if(rc == -1)

{

PPANIC("bind() failed");

}

rc = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));

if(rc == -1)

{

PPANIC("setsockopt(IP_PKTINFO) failed");

}

for (i = 0; mcast_groups[i] != NULL; i++)

{

imreq.imr_multiaddr.s_addr = inet_addr(mcast_groups[i]);

imreq.imr_interface.s_addr = INADDR_ANY;

rc = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&imreq, sizeof(struct ip_mreq));

if (rc != 0)

{

PPANIC("joing mcast group failed");

}

}

FD_SET(sock, &master);

while(1)

{

read_fds = master;

rc = select(sock + 1, &read_fds, NULL, NULL, NULL);

if (rc == 0)

{

continue;

}

if(rc == -1)

{

PPANIC("select() failed");

}

if(FD_ISSET(sock, &read_fds))

{

char buf[1024];

int inb;

char ctrl_msg_buf[1024];

struct iovec iov[1];

iov[0].iov_base = buf;

iov[0].iov_len = 1024;

struct msghdr msg_hdr = {

.msg_iov = iov,

.msg_iovlen = 1,

.msg_name = NULL,

.msg_namelen = 0,

.msg_control = ctrl_msg_buf,

.msg_controllen = sizeof(ctrl_msg_buf),

};

struct cmsghdr *ctrl_msg_hdr;

inb = recvmsg(sock, &msg_hdr, 0);

if (inb < 0)

{

PPANIC("recvmsg() failed");

}

for (ctrl_msg_hdr = CMSG_FIRSTHDR(&msg_hdr); ctrl_msg_hdr != NULL; ctrl_msg_hdr = CMSG_NXTHDR(&msg_hdr, ctrl_msg_hdr))

{

if (ctrl_msg_hdr->cmsg_level == IPPROTO_IP && ctrl_msg_hdr->cmsg_type == IP_PKTINFO)

{

struct in_pktinfo *pckt_info = (struct in_pktinfo *)CMSG_DATA(ctrl_msg_hdr);

printf("got data for mcast group: %s\n", inet_ntoa(pckt_info->ipi_addr));

break;

}

}

printf("|");

for (i = 0; i < inb; i++)

printf("%c", isprint(buf[i])?buf[i]:'?');

printf("|\n");

#if STATS_PATCH

rc = fstat(sock, &stat_buf);

if (rc == -1)

{

perror("fstat() failed");

} else {

printf("st_atime: %d\n", stat_buf.st_atime);

printf("st_mtime: %d\n", stat_buf.st_mtime);

printf("st_ctime: %d\n", stat_buf.st_ctime);

}

#endif

}

}

return 0;

}下面的代码不会解决OP问题,但可能会指导人们处理类似的要求

(编辑)一个人不应该在深夜做这样的事情......即使有了这个解决方案,你也只能通过选择获得fd处理的订单 - 而且这不会给你关于帧到达时间的指示。

如here所述,目前无法检索套接字的顺序或它们更改的时间戳,因为没有为套接字inode设置所需的回调。但是,如果您能够修补内核,则可以通过在select系统调用中设置时间来解决此问题。

以下补丁可能会给你一个想法:

diff --git a/fs/select.c b/fs/select.c

index 467bb1c..3f2927e 100644

--- a/fs/select.c

+++ b/fs/select.c

@@ -435,6 +435,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)

for (i = 0; i < n; ++rinp, ++routp, ++rexp) {

unsigned long in, out, ex, all_bits, bit = 1, mask, j;

unsigned long res_in = 0, res_out = 0, res_ex = 0;

+ struct timeval tv;

+

+ do_gettimeofday(&tv);

in = *inp++; out = *outp++; ex = *exp++;

all_bits = in | out | ex;

@@ -452,6 +455,16 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)

f = fdget(i);

if (f.file) {

const struct file_operations *f_op;

+ struct kstat stat;

+

+ int ret;

+ u8 is_sock = 0;

+

+ ret = vfs_getattr(&f.file->f_path, &stat);

+ if(ret == 0 && S_ISSOCK(stat.mode)) {

+ is_sock = 1;

+ }

+

f_op = f.file->f_op;

mask = DEFAULT_POLLMASK;

if (f_op->poll) {

@@ -464,16 +477,22 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)

res_in |= bit;

retval++;

wait->_qproc = NULL;

+ if(is_sock && f.file->f_inode)

+ f.file->f_inode->i_ctime.tv_sec = tv.tv_sec;

}

if ((mask & POLLOUT_SET) && (out & bit)) {

res_out |= bit;

retval++;

wait->_qproc = NULL;

+ if(is_sock && f.file->f_inode)

+ f.file->f_inode->i_ctime.tv_sec = tv.tv_sec;

}

if ((mask & POLLEX_SET) && (ex & bit)) {

res_ex |= bit;

retval++;

wait->_qproc = NULL;

+ if(is_sock && f.file->f_inode)

+ f.file->f_inode->i_ctime.tv_sec = tv.tv_sec;

}

/* got something, stop busy polling */

if (retval) {笔记:

这是......仅适合你:) - 不要指望它在主线

在测试每个相关的fd之前调用

do_gettimeofday()。

为了获得更高的粒度,这应该在每次迭代中完成(并且仅在需要时)。因为stat-interface只提供一秒的粒度

你可以(!UGLY!)使用剩余的时间属性将秒的分数映射到那些字段。

这是使用内核3.16.0完成的,并没有经过充分测试。不要在太空船或医疗设备中使用它。如果您想尝试一下,请获取文件系统映像(例如https://people.debian.org/~aurel32/qemu/amd64/debian_wheezy_amd64_standard.qcow2)并使用qemu进行测试:

sudo qemu-system-x86_64 -kernel arch / x86 / boot / bzImage -hda debian_wheezy_amd64_standard.qcow2 -append“root = / dev / sda1”

linux 多个select,Linux select()和多个套接字的FIFO排序?相关推荐

  1. linux获取fifo中的数据数量,Linux select()和多个套接字的FIFO排序?

    您可以使用IP_PKTINFO将数据包被发送到组播组的地址 - 即使套接字认购一堆组播组.完成此操作后,您将按顺序获取数据包并按组地址进行过滤.看下面的例子: #include #include #i ...

  2. linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时

    一.使用alarm 函数设置超时 C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13   void handler( int sig) { } signal(SIGALRM ...

  3. linux c ip数据包,如何在Linux上的C / C ++中使用ipv6 udp套接字进行多播?

    (英语不是我的母语,不用担心某些句子是否很奇怪:). 我正在开发 PONG游戏, 并且通过创建一些类来帮助我管理窗口,事件-和 网络, 因为我在游戏中添加了 LAN功能 ,但是当前您必须输入您想与之联 ...

  4. Linux内核套接字(Socket)的设计与实现

    一个套接字是一个通信端点的抽象,就如使用文件描述符来访问一个文件一样,应用程序使用套接字描述符来访问套接字. 在Linux中实现了一套机制,使套接字的实现与文件描述符实现一样,使应用程序可以像访问文件 ...

  5. 简单谈一点linux内核中套接字的bind机制--数据结构以及端口确定

    众所周知,创建一个套接字可以bind到一个特定的ip地址和端口,实际上套接字这一概念代表了TCP/IP协议栈的应用层标识,协议栈中的应用层就是通过一个ip地址和一个端口号标识的,当然这仅仅是对于TCP ...

  6. linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同. 字符设备和块设备对应/dev下的一个设备文件.而网络设备不存在这样的设备文件.网络设备使用套接字socket访问,虽然也使用read, ...

  7. linux find工作原理,Linux基础教程:find 与 xargs

    find 命令的工作方式 find命令的工作方式如下:沿着文件层次结构向下遍历,匹配符合条件的文件,并执行相应的操作. find命令异常强大,因为它允许您按文件名.文件类型.用户甚至是时间戳查找文件. ...

  8. linux篇【12】:网络套接字<前序>—网络基础+udp套接字

    目录 一.网络基础 1.认识 "协议" 举例: 2.协议分层 (1)软件分层 (2)协议分层 3.OSI七层模型 4.TCP/IP五层(或四层)模型 5.网络和操作系统之间的关系 ...

  9. linux全局查找字符串,linux全局搜索命令

    1. 前言 本文主要介绍Linux系统下有哪些全局搜索命令,并讲解相关命令的使用方法与日常使用案例. 我们先来了解一下Linux下主要的5个全局搜索的命令工具.他们分别是find,locate,gre ...

最新文章

  1. 什么是大数据口子_大数据分析师年薪几十万,学什么专业才能从事大数据?
  2. R语言ggplot2可视化增加轴标签(ticks)和轴标题(title)之间的距离实战
  3. eclipse 无法解析导入 javax.servlet 的解决方法
  4. IP修改器的作用以及用途
  5. php 字符串隔位取,PHP 字符串截取字符串函数
  6. Codeforces 766E
  7. abap 生成流水号每天从1开始_条码软件如何制作循环流水号
  8. linux+qt+定时精度,Qt QTimer测试定时精度
  9. 为什么不能在scrollview中直接添加一个image,然后使animation.begin()??
  10. oracle blob 限制大小_Oracle的INSTANCE CAGING在数据库资源池中的作用
  11. QBC检索和本地SQL检索
  12. 案例4-4 Windows消息队列 (25 分)(优先队列的优先级设定)
  13. Vue3+ts+vite 国际化处理
  14. MacBook M1安装Git与Git可视化工具---kalrry
  15. EasyUI 中combobox利用拼音进行检索
  16. 名帖22 杨沂孙 篆书《对联五幅》
  17. 12306bypass推送
  18. mysql 按日期分组求和
  19. 气象数据免费下载(超级好用)
  20. 电影《小萝莉的猴神大叔》观后感

热门文章

  1. 怎么分辨学校计算机sql版本,怎么筛选出每个年级每个学校有多少个班级
  2. list选取多个元素 python_【幼儿园级】0基础学python一本通(上)——AI未来系列1...
  3. java 终态类,javaoo,继承,抽象类,终态类,访问修饰符!
  4. css动画与js动画的区别
  5. 【OpenCV 例程200篇】68. 连续周期信号的傅立叶级数
  6. Python 小白从零开始 PyQt5 项目实战(8)汇总篇(完整例程)
  7. typescript 接口 java_Typescript基础(4)——接口
  8. java英语词汇_java常用的英语单词
  9. python glob.glob使用
  10. STL10-deque容器