C UDP多播套接字不';t在linux 64位平台上工作

C UDP多播套接字不';t在linux 64位平台上工作,c,linux,multicastsocket,C,Linux,Multicastsocket,我写了一个非常小的C代码来打开UDP多播套接字,它在 一个32位的平台,但当我重新编译代码并在Linux64上尝试时 它不工作。程序在服务器上处于非限定挂起状态 recvfrom()函数。我检查了udp帧是否在网络上实际接收到 使用tcpdump指定网络接口,但一切正常。做 有人知道我的代码有什么问题吗 以下是第一个代码(在您的评论之前): #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 静态字符*server=“231.180.0.1”; 静态字符*networ

我写了一个非常小的C代码来打开UDP多播套接字,它在 一个32位的平台,但当我重新编译代码并在Linux64上尝试时 它不工作。程序在服务器上处于非限定挂起状态 recvfrom()函数。我检查了udp帧是否在网络上实际接收到 使用tcpdump指定网络接口,但一切正常。做 有人知道我的代码有什么问题吗

以下是第一个代码(在您的评论之前):

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
静态字符*server=“231.180.0.1”;
静态字符*network=“66.46.40.10”;
静态int端口=50001;
socketAddr中的静态结构sockaddr_;
静态无符号int-socketDesc;
long-toLong(无符号字符*msg,整数偏移量);
内部主(空){
结构ip_mreq mreq;
int bindDesc、socketOptDesc;
int=1;
unsigned int-socketLength=sizeof(socketAddr);
//分配
memset((char*)&socketAddr,0,sizeof(socketAddr));
memset(&mreq,0,sizeof(struct ip_mreq));
/*
*创建要在其上接收的数据报套接字。
*/
printf(#Init socket(服务器=%s网络=%s端口=%d)\n),服务器,网络,端口;
socketDesc=插座(天线、插座、IP协议);
如果(socketDesc<0){
perror(“套接字()失败”);
}否则{
/*
*启用SO_REUSEADDR以允许此操作的多个实例
*用于接收多播数据报副本的应用程序。
*/
socketOptDesc=setsockopt(socketDesc,SOL_SOCKET,SO_REUSEADDR,(char*)和reuse,sizeof(reuse));
如果(socketOptDesc<0){
perror(“setsockopt()失败”);
}否则{
/*
*使用IP地址绑定到正确的端口号
*指定为INADDR_ANY。
*/
socketAddr.sin_family=AF_INET;
socketAddr.sin_port=htons(端口);
socketAddr.sin\u addr.s\u addr=INADDR\u ANY;
bindDesc=bind(socketDesc,(struct sockaddr*)和socketAddr,sizeof(socketAddr));
if(bindDesc<0){
perror(“绑定()失败”);
}否则{
/*
*在本地接口上加入多播组。
*请注意,此IP_添加_成员资格选项必须为
*为多播通过的每个本地接口调用
*数据报将被接收。
*/
mreq.imr\u multiaddr.s\u addr=inet\u addr(服务器);
mreq.imr\u interface.s\u addr=inet\u addr(网络);
socketOptDesc=SetSocketDesc(socketDesc,IPPROTO_IP,IP_ADD_会员资格,(char*)和mreq,sizeof(mreq));
如果(socketOptDesc<0){
perror(“setsockopt()失败”);
}否则{
printf(“已成功创建套接字!\n”);
}
}
}
}
/*
*采集环路
*/
printf(“开始接收循环…\n”);
长lastFrameNumber=-1;
int=0;
而(1){
长帧数=-1;
无符号字符缓冲区[65536];
//帧采集
int ret=recvfrom(socketDesc,buffer,65536,0,(struct sockaddr*)和socketAddr,&socketLength);
如果(ret<0){
perror(“recvfrom()失败”);
}
//读帧号
frameNumber=toLong(缓冲区,28);
如果(帧编号<0){
//上下文框架
}else if(frameNumber==0){
printf(“无效帧(帧编号=0)\n”);
}否则{
如果(frameNumber>1&&frameNumber!=(lastFrameNumber+1)){
printf(“%ld帧从帧%ld丢失\n”,帧号-lastFrameNumber-1,lastFrameNumber+1);
}
}
lastFrameNumber=帧编号;
if(frameNumber==1){
如果(nbDots>50){
printf(“.\n”);
nbDots=0;
}否则{
printf(“.”);
fflush(stdout);
}
nbDots++;
}
}
返回退出成功;
}
/* ======================================================================
*从指定的偏移量读取4个字节,并将其转换为长值。
*
*@input msg
*表示消息的字节数组。
*@输入偏移量
*字节偏移量。
*@返回
*表示帧编号的长值。
* ====================================================================*/
长toLong(无符号字符*msg,整数偏移){
长期价值;
int字节0;//位31..24
int字节1;//位23..16
int字节2;//位15..8
int字节3;//位7..0
字节0=(0x000000FF&(int)msg[offset+0]);
字节1=(0x000000FF&(int)msg[offset+1]);
字节2=(0x000000FF&(int)msg[offset+2]);
字节3=(0x000000FF&(int)msg[offset+3]);

值=((长)(字节0代码中一个明显的64位问题是recvfrom的最后一个参数应该是指向
socklen_t
的指针,而不是代码中的
unsigned int
socklen_t
很可能是64位机器上的64位变量,而
unsigned int
很可能是32位ts

另一个问题是socketDesc没有签名。文件描述符总是有签名的,这样您就可以实际检测返回它们的函数中的错误。您对所有函数中的错误的检查将不起作用,因此您的代码可能在很早以前就失败了,而您没有注意到

另一个可能的问题是您的
toLong
函数,
long
在64位平台上通常是64位的,而您将其视为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.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;
}
#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;
}