- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我写了一个非常小的 C 代码来打开一个 UDP 多播套接字,它在一个 32 位平台,但是当我重新编译我的代码并在 linux 64 上尝试时位平台它不起作用。该计划无限期挂起recvfrom() 函数。我检查了 udp 帧是否真的收到了使用 tcpdump 指定的网络接口(interface),但一切正常。做有人知道我的代码有什么问题吗?
这是第一个代码(在您发表评论之前):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <math.h>
#include <errno.h>
static char* server = "231.180.0.1";
static char* network = "66.46.40.10";
static int port = 50001;
static struct sockaddr_in socketAddr;
static unsigned int socketDesc;
long toLong (unsigned char* msg, int offset);
int main (void) {
struct ip_mreq mreq;
int bindDesc, socketOptDesc;
int reuse = 1;
unsigned int socketLength = sizeof(socketAddr);
// Allocation
memset((char *) &socketAddr, 0, sizeof(socketAddr));
memset(&mreq, 0, sizeof(struct ip_mreq));
/*
* Create a datagram socket on which to receive.
*/
printf("# Init socket (server=%s network=%s port=%d)\n", server, network, port);
socketDesc = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (socketDesc < 0) {
perror("socket() failed");
} else {
/*
* Enable SO_REUSEADDR to allow multiple instances of this
* application to receive copies of the multicast datagrams.
*/
socketOptDesc = setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse));
if (socketOptDesc < 0) {
perror("setsockopt() failed");
} else {
/*
* Bind to the proper port number with the IP address
* specified as INADDR_ANY.
*/
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(port);
socketAddr.sin_addr.s_addr = INADDR_ANY;
bindDesc = bind(socketDesc, (struct sockaddr*) &socketAddr, sizeof(socketAddr));
if (bindDesc < 0) {
perror("bind() failed");
} else {
/*
* Join the multicast group on the local interface.
* Note that this IP_ADD_MEMBERSHIP option must be
* called for each local interface over which the multicast
* datagrams are to be received.
*/
mreq.imr_multiaddr.s_addr = inet_addr(server);
mreq.imr_interface.s_addr = inet_addr(network);
socketOptDesc = setsockopt(socketDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
if (socketOptDesc < 0) {
perror("setsockopt() failed");
} else {
printf("# Socket created successfully !\n");
}
}
}
}
/*
* Acquisition Loop
*/
printf("# Starting reception loop...\n");
long lastFrameNumber = -1;
int nbDots = 0;
while (1) {
long frameNumber = -1;
unsigned char buffer[65536];
// Frame Acquisition
int ret = recvfrom(socketDesc, buffer, 65536, 0, (struct sockaddr *) &socketAddr, &socketLength);
if (ret < 0) {
perror("recvfrom() failed");
}
// Reading frame number
frameNumber = toLong(buffer, 28);
if (frameNumber < 0) {
// Context Frame
} else if (frameNumber == 0) {
printf("Invalid frame (frameNumber=0)\n");
} else {
if (frameNumber > 1 && frameNumber != (lastFrameNumber + 1)) {
printf("%ld frame(s) lost from frame %ld\n", frameNumber - lastFrameNumber - 1, lastFrameNumber + 1);
}
}
lastFrameNumber = frameNumber;
if (frameNumber == 1) {
if (nbDots > 50) {
printf(".\n");
nbDots = 0;
} else {
printf(".");
fflush(stdout);
}
nbDots++;
}
}
return EXIT_SUCCESS;
}
/* ======================================================================
* Read 4 bytes from the specified offset and convert it to a long value.
*
* @input msg
* Byte array representing the message.
* @input offset
* Byte offset.
* @return
* Long value representing the frame number.
* ====================================================================*/
long toLong (unsigned char* msg, int offset) {
long value;
int byte0; // bits 31..24
int byte1; // bits 23..16
int byte2; // bits 15..8
int byte3; // bits 7..0
byte0 = (0x000000FF & ((int) msg[offset + 0]));
byte1 = (0x000000FF & ((int) msg[offset + 1]));
byte2 = (0x000000FF & ((int) msg[offset + 2]));
byte3 = (0x000000FF & ((int) msg[offset + 3]));
value = ((long) (byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3)) & 0xFFFFFFFFL;
return value;
}
编辑:我用你的评论更新了我的代码,但它也不起作用 :( 另外,我忘了说网络正在使用 VLAN。网络接口(interface)是 eth.40,位于 66.46.40.100,但它在 32 位平台上工作,所以它可能不是问题所在。
这是新代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <math.h>
#include <errno.h>
static char* server = "231.180.0.1";
static char* network = "66.46.40.100";
static uint16_t port = 50001;
long toLong (unsigned char* msg, int offset);
int main (void) {
struct sockaddr_in socketAddr;
struct ip_mreq mreq;
int bindDesc, socketDesc, socketOptDesc;
socklen_t reuse = 1;
socklen_t socketLength = sizeof(socketAddr);
// Allocation
memset((char *) &socketAddr, 0, sizeof(socketAddr));
memset(&mreq, 0, sizeof(struct ip_mreq));
/*
* Create a datagram socket on which to receive.
*/
printf("# Init socket (server=%s network=%s port=%d)\n", server, network, port);
socketDesc = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (socketDesc < 0) {
perror("socket() failed");
} else {
/*
* Enable SO_REUSEADDR to allow multiple instances of this
* application to receive copies of the multicast datagrams.
*/
socketOptDesc = setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, (void *) &reuse, sizeof(reuse));
if (socketOptDesc < 0) {
perror("setsockopt() failed");
} else {
/*
* Bind to the proper port number with the IP address
* specified as INADDR_ANY.
*/
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(port);
socketAddr.sin_addr.s_addr = INADDR_ANY;
bindDesc = bind(socketDesc, (struct sockaddr*) &socketAddr, sizeof(socketAddr));
if (bindDesc < 0) {
perror("bind() failed");
} else {
/*
* Join the multicast group on the local interface.
* Note that this IP_ADD_MEMBERSHIP option must be
* called for each local interface over which the multicast
* datagrams are to be received.
*/
mreq.imr_multiaddr.s_addr = inet_addr(server);
mreq.imr_interface.s_addr = inet_addr(network);
socketOptDesc = setsockopt(socketDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
if (socketOptDesc < 0) {
perror("setsockopt() failed");
} else {
printf("# Socket created successfully !\n");
}
}
}
}
/*
* Acquisition Loop
*/
printf("# Starting reception loop...\n");
long lastFrameNumber = -1;
int nbDots = 0;
while (1) {
unsigned char buffer[65536];
// Frame Acquisition
ssize_t ret = recvfrom(socketDesc, buffer, 65536, 0, (struct sockaddr *) &socketAddr, &socketLength);
if (ret < 0) {
perror("recvfrom() failed");
} else {
printf("# Receiving frame\n");
}
}
return EXIT_SUCCESS;
}
最佳答案
您在代码中遇到的一个明显的 64 位问题是,recvfrom 的最后一个参数应该是指向 socklen_t
的指针,而不是您拥有的 unsigned int
在你的代码中。 socklen_t
很可能是 64 位机器上的 64 位变量,而 unsigned int
很可能是 32 位。
另一个问题是 socketDesc 未签名。文件描述符总是有符号的,这样你就可以从返回它们的函数中实际检测到错误。您对所有函数的错误检查将不起作用,因此您的代码可能更早失败而您没有注意到。
另一个可能的问题是您的 toLong
函数,long
在 64 位平台上通常是 64 位,而您将其视为 32 位值。
尝试使用警告构建,编译器应该很有帮助。这绝对是您的编译器会警告您的事情。如果这没有帮助,请仔细检查您调用的所有函数的手册页,并检查类型是否正确。
关于c - UDP 多播套接字在 linux 64 位平台上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28146991/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
Linux 管道可以缓冲多少数据?这是可配置的吗? 如果管道的两端在同一个进程中,但线程不同,这会有什么不同吗? 请注意:这个“同一个进程,两个线程”的问题是理论上的边栏,真正的问题是关于缓冲的。 最
我找到了here [最后一页] 一种有趣的通过 Linux 启动 Linux 的方法。不幸的是,它只是被提及,我在网上找不到任何有用的链接。那么有人听说过一种避免引导加载程序而使用 Linux 的方法
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我试图了解 ld-linux.so 如何在 Linux 上解析对版本化符号的引用。我有以下文件: 测试.c: void f(); int main() { f(); } a.c 和 b.c:
与 RetroPie 的工作原理类似,我可以使用 Linux 应用程序作为我的桌面环境吗?我实际上并不需要像实际桌面和安装应用程序这样的东西。我只需要一种干净简单的方法来在 RaspberryPi 上
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
有什么方法可以覆盖现有的源代码,我应该用 PyQt、PyGTK、Java 等从头开始构建吗? 最佳答案 如果您指的是软件本身而不是它所连接的存储库,那么自定义应用程序的方法就是 fork 项目。据我所
我的情况是:我在一个磁盘上安装了两个 linux。我将第一个安装在/dev/sda1 中,然后在/dev/sda2 中安装第二个然后我运行第一个系统,我写了一个脚本来在第一个系统运行时更新它。
我在 i2c-0 总线上使用地址为 0x3f 的系统监视器设备。该设备在设备树中配置有 pmbus 驱动程序。 问题是,加载 linux 内核时,这个“Sysmon”设备没有供电。因此,当我在总线 0
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我正试图在 linux 模块中分配一大块内存,而 kalloc 做不到。 我知道唯一的方法是使用 alloc_bootmem(unsigned long size) 但我只能从 linux 内核而不是
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我有 .sh 文件来运行应用程序。在该文件中,我想动态设置服务器名称,而不是每次都配置。 我尝试了以下方法,它在 CentOS 中运行良好。 nohup /voip/java/jdk1.8.0_71/
我是在 Linux 上开发嵌入式 C++ 程序的新手。我有我的 Debian 操作系统,我在其中开发和编译了我的 C++ 项目(一个简单的控制台进程)。 我想将我的应用程序放到另一个 Debian 操
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我使用4.19.78版本的稳定内核,我想找到带有企鹅二进制数据的C数组。系统启动时显示。我需要在哪里搜索该内容? 我在 include/linux/linux_logo.h 文件中只找到了一些 Log
我知道可以使用 gdb 的服务器模式远程调试代码,我知道可以调试针对另一种架构交叉编译的代码,但是是否可以更进一步,从远程调试 Linux 应用程序OS X 使用 gdbserver? 最佳答案 当然
是否有任何可能的方法来运行在另一个 Linux 上编译的二进制文件?我知道当然最简单的是在另一台机器上重建它,但假设我们唯一能得到的是一个二进制文件,那么这可能与否? (我知道这可能并不容易,但我只是
我是一名优秀的程序员,十分优秀!