动态报式套接字

1.存在的问题

上一次我们在协议中定义了这样一个内容

#ifndef __PROTO_H__
#define __PROTO_H__

#define NAMESIZE 11

#include <stdint.h>

#define RCVPORT 1989

struct msg_st
{
        uint8_t name[NAMESIZE];
        uint32_t math;
        uint32_t eng;

}__attribute((packed));

#endif

这个结构体中的name成员的大小 到底该设定为多少呢?这是一个问题,小了不够写,大了增加网络传输时的负载

2.改进

#ifndef __PROTO_H__
#define __PROTO_H__


//udp推荐长度-报头-两个32位
#define NAMEMAX (512-8-8)

#include <stdint.h>

#define RCVPORT 1989

struct msg_st
{
        uint32_t math;
        uint32_t eng;
        uint8_t name[1];
}__attribute((packed));

#endif

我们用变长结构体来解决这一问题,前面八个字节是固定不变的,后面的name分配给他的大小,一直在变化

3.demo

用例中没有处理的很精细,如内存泄漏什么的,自行补充
snder.c

#define SIZE 40 



int main(int argc, char *argv[])
{
   int sd;
   struct sockaddr_in  raddr;
   struct msg_st * pBuf;
   int size;

	//命令行传入ip 传入name
   if(argc < 3)
   {
           fprintf(stderr, "No Enough\n");
           exit(1);
   }
   
   sd = socket(AF_INET, SOCK_DGRAM, 0);
   if(sd < 0)
   {
           perror("socket()");
           exit(1);
   }

	//nameLen是否超过最大长度
   if(strlen(argv[2]) > NAMEMAX)
   {
           fprintf(stderr, "Too Long Name\n");
           exit(1);
   }
	
	//实际分配的size 是原结构体的大小 + name长度 
   size = sizeof(strlen(argv[2])) + sizeof(struct msg_st);
   pBuf = malloc(size);
   if(NULL == pBuf)
   {
           fprintf(stderr, "malloc()\n");
           exit(1);
   }

   strcpy(pBuf->name, argv[2]);
   pBuf->math = htonl(rand()%100);
   pBuf->eng = htonl(rand()%100);

   raddr.sin_family = AF_INET;
   raddr.sin_port = htons(RCVPORT);
   inet_pton(AF_INET, argv[1], &raddr.sin_addr);

	//发送时候 发送的是当前的size 而不是一个固定的size
   if(sendto(sd, pBuf, size, 0, (void*)&raddr, sizeof(raddr)) < 0)
   {
           perror("sendto()");
           exit(1);
   }

   puts("OK");

   close(sd);

   return 0;
}

rcver.c

#define SIZE 40 



int main()
{
    int sd;
    struct sockaddr_in laddr , raddr;
    struct msg_st *pBuf;
    socklen_t raddr_len;
    char ipstr[SIZE];
    int bufsize;

	//我们不知道发送方会发送多大类型的结构体 我们只能按照最大的来接受
    bufsize = sizeof(struct msg_st)-1 + NAMEMAX;
    pBuf = malloc(bufsize);
    if(NULL == pBuf)
    {
            fprintf(stderr, "malloc()\n");
            exit(1);
    }


    sd = socket(AF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP*/);
    if(sd < 0)
    {
            perror("socket()");
            exit(1);
    }

    laddr.sin_family = AF_INET;
    laddr.sin_port = htons(RCVPORT);
    inet_pton(AF_INET, "0.0.0.0", &laddr.sin_addr);

    if(bind(sd, (void*)&laddr, sizeof(laddr)) < 0)
    {
            perror("bind()");
            exit(1);
    }

    /*!!!!!*/
    raddr_len = sizeof(raddr);

    while(1)
    {
    		//此处改动size
            recvfrom(sd, pBuf, bufsize, 0, (void *)&raddr, &raddr_len);
            inet_ntop(AF_INET, &raddr.sin_addr, ipstr, SIZE);
            printf("MSG FROM **** %s:%d*****\n", ipstr, ntohs(raddr.sin_port));
            printf("NMAE = %s\n", pBuf->name);
            printf("MATH = %d Eng = %d\n", ntohl(pBuf->math), ntohl(pBuf->eng));
    }

    close(sd);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值