【问题标题】:passing structures in messages of mqueue在 mqueue 的消息中传递结构
【发布时间】:2015-02-13 08:39:59
【问题描述】:

我正在尝试读取一个 IP/RAW 套接字数据包及其参数(例如指向 IP 数据包的字符指针及其大小),将其放入 WRONLY 模式的 mqueue 中,并在 RDONLY 模式下从队列中检索相同的参数.我正在使用消息(msg)的结构来发送和接收。发送 msg 时,这两个参数都成功放入队列中,但在检索时返回我分段错误。我的发送和接收文件如下:

mq_send.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<mqueue.h>
#include<errno.h>
#include<netinet/ip_icmp.h>   
#include<netinet/udp.h> 
#include<netinet/tcp.h>  
#include<netinet/ip.h>
#include<netinet/in.h>
#include<netinet/if_ether.h>
#include<net/ethernet.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
#include"external.h"

#define QUEUE_NAME  "/test_queue"
#define MAX_SIZE    71680

#define CHECK(x) \
    do { \
        if (!(x)) { \
            fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
            perror(#x); \
            exit(-1); \
        } \
    } while (0) \


struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;

struct mymsg
{
    char buff[MAX_SIZE];
    int size;
};


int main(int argc, char **argv)
{
    mqd_t mq;
    struct mymsg m;
    struct mq_attr attr;
    //char buff[MAX_SIZE];
    unsigned char* buffer = (unsigned char*) malloc(sizeof(65536));
    int saddr_size,sock_raw;
    struct sockaddr saddr;
    int data_size;

    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;

    mq = mq_open(QUEUE_NAME, O_CREAT | O_WRONLY, 0644, &attr);
    CHECK((mqd_t)-1 != mq);

    memset(buffer, 0, MAX_SIZE);    

    sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
    if(sock_raw < 0)
    {
       perror("Socket Error\n");
       return 1;
    }
    saddr_size = sizeof saddr;
    data_size = recvfrom(sock_raw , buffer ,65536 , 0 , &saddr , (socklen_t*)&saddr_size);

    if(data_size <0 )
    {
       printf("Recvfrom error , failed to get packets\n");
       return 1;
    }

    memcpy(m.buff,buffer,65536);
    m.size=data_size;

    //char *a="hi";
    //CHECK(0 <= mq_send(mq, (char *)&a, MAX_SIZE, 0));
    CHECK(0 <= mq_send(mq, (char *)&m, MAX_SIZE, 0));

    printf("Packet msg:%s size:%d\n",buffer,data_size);
    printf("Sent msg:%s size:%d\n",m.buff,m.size);

    ProcessPacket(m.buff , m.size);

    CHECK((mqd_t)-1 != mq_close(mq));

    close(sock_raw);

    return 0;
}

mq_receive.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<mqueue.h>
#include<errno.h>
#include<netinet/ip_icmp.h>   
#include<netinet/udp.h> 
#include<netinet/tcp.h>  
#include<netinet/ip.h>
#include<netinet/in.h>
#include<netinet/if_ether.h>
#include<net/ethernet.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
#include"external.h"

#define QUEUE_NAME  "/test_queue"
#define MAX_SIZE    71680

#define CHECK(x) \
    do { \
        if (!(x)) { \
            fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
            perror(#x); \
            exit(-1); \
        } \
    } while (0) \

struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;

typedef struct mymsg
{
    unsigned char *buff;
    int size;
}msg;

int main(int argc, char *argv[])
{
    mqd_t mq;
    msg *m=(msg *)malloc(sizeof(msg));
    m->buff=(unsigned char*) malloc(sizeof(MAX_SIZE));
    int data_size;

    mq = mq_open(QUEUE_NAME, O_RDONLY);
    CHECK((mqd_t)-1 != mq);

    memset(m->buff, 0, MAX_SIZE+1);

    ssize_t bytes_read;


    bytes_read = mq_receive(mq, (char *)m, MAX_SIZE, NULL);
    CHECK(bytes_read >= 0);
    printf("Received buff:%s size:%d\n", m->buff,m->size);
    //ProcessPacket(m.buff , data_size);

    /* cleanup */
    CHECK((mqd_t)-1 != mq_close(mq));
    CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME));

    return 0;
}

mqueue_send.c 的输出:

bcg@BCGA53:~/Desktop/mqueue$ sudo ./mq_send 数据包味精:��������M���� 大小:60 已发送消息:��������M��� 大小:60

mq_receive.c 的输出:

bcg@BCGA53:~/Desktop/mqueue$ sudo ./mq_receive 分段故障

【问题讨论】:

  • 至于崩溃,您是否尝试在调试器中运行以找出崩溃的在哪里
  • 好吧,mq_send(mq, (char *)&amp;m, MAX_SIZE, 0)) 已经错了。您发送的是MAX_SIZE,它不是m 的大小。它只发送结构的第一个字段。发送中省略了size 成员。在我看来sizeof(m) 在这种情况下会更合适,因为它是一个独立的结构(没有指针)。坦率地说,我不明白为什么您的size 不是您发送的第一个,然后是size 字节。
  • 嗨,哥们,我正在尝试将指向数据包的指针及其大小发送到队列,以便可以在接收端轻松处理它。 recvfrom() 函数返回数据包(由 char* 指向)及其大小(int)以进行处理。它是正确的还是我哪里出错了?你的建议..

标签: c segmentation-fault mqueue


【解决方案1】:
unsigned char* buffer = (unsigned char*) malloc(sizeof(65536));

上面的代码分配了可以容纳sizeof(65536)字节的内存。问题是 sizeof(65536)sizeof(int) 相同,通常是 4 或 8 个字节。

你应该使用这个:

unsigned char* buffer = (unsigned char*) malloc(sizeof(char[65536]));

或者这个

unsigned char* buffer = (unsigned char*) malloc(65536);

还有其他错误 - 例如,您在 mq_send() 中使用了 MAX_SIZE,而您应该使用 sizeof(m)。您的错误的根本原因是上述问题。

事实上,这种分配是没有意义的(至少在您上面提供的代码中),因为您可以直接接收到您的消息结构中 - 那时您不会看到这个问题。

【讨论】:

  • 对不起,您对 malloc() 的建议给了我一个分段错误。但是,我使用了您的第二个建议,例如 CHECK(0 = 0: Message too long 错误
  • @AshokKumar 您在其他地方有一个错误,从您在这里和上面的 cmets 中写的内容来看,您似乎并不了解您实际在做什么。您没有通过队列传递指针 - 您正在传递缓冲区的 copy (但不是整个消息)。您最初的 malloc() 调用完全被破坏(在两个程序中!),而上面的两个调用都是正确的(假设您真的想要分配 65536 字节)。
猜你喜欢
  • 2013-09-04
  • 2015-10-18
  • 2010-11-14
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-23
相关资源
最近更新 更多