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;
}