编译: gcc udp_server.c -o s
gcc udp_client.c -o c
先运行服务器: ./s
再打开一个终端,运行客户端。 ./c
客户端输入任意字符串会直接返回给服务器。  4. 基于步骤2/3通过udp实现信令在client/server之间传输,只写出结构即可clien.c #define SERVER_PORT 8888
#define MAX_BUF_SIZE 1024
typedef struct sockaddr SA;
void sendfrm_thread(int sockfd,const struct sockaddr_in *addr,int len)
{
u8 data[FRM_DATA_MAX_LEN]={0x1,0x2,0x3,0x4};
int addrlen,frmlen;
struct sockaddr_in addr_server;
u16 param = 0x9527;
u8 rawdata[MAX_FRM_LEN] = {0};
while(1)
{
frmlen = msg_send(rawdata,MSG_TYPE_QUERY, param, 1, data, 4);
sendto(sockfd,rawdata,frmlen,0,(SA *)addr,len);
sleep(2);
}
}
int main(int argc,char **argv)
{
int sockfd;
struct sockaddr_in addr;
if(argc!=2)
{
fprintf(stderr,"Usage:%s server_ip\n",argv[0]);
exit(1);
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
fprintf(stderr,"Socket Error:%s\n",strerror(errno));
exit(1);
}
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_port=htons(SERVER_PORT);
if(inet_aton(argv[1],&addr.sin_addr)<0)
{
fprintf(stderr,"Ip error:%s\n",strerror(errno));
exit(1);
}
sendfrm_thread(sockfd,&addr,sizeof(struct sockaddr_in));
close(sockfd);
}
server.c void rcvfrm_thread(int sockfd)
{
int ret;
struct sockaddr_in addr;
int addrlen,len;
PENG_FRM_MSG_S msg;
PENG_FRM_MSG_S *pmsg = &msg;
char buf[MAX_MSG_SIZE];
addrlen = sizeof(struct sockaddr_in);
while(1) {
bzero(buf,sizeof(buf));
len=recvfrom(sockfd,buf,MAX_MSG_SIZE,0,(struct sockaddr*)&addr,&addrlen);
buf[len]=0;
ret = frm_parse(pmsg,buf,len);
printf("\n[msg]<<< cmd:%x param:%x,len:%x,subcmd:%x\n",
pmsg->cmd,pmsg->param,pmsg->len,pmsg->subcmd);
//print_array("[data]<<<",pmsg->data,pmsg->len-1);
}
}
int main(void)
{
int sockfd;
struct sockaddr_in addr;
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
fprintf(stderr,"Socket Error:%s\n",strerror(errno));
exit(1);
}
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(SERVER_PORT);
if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0)
{
fprintf(stderr,"Bind Error:%s\n",strerror(errno));
exit(1);
}
rcvfrm_thread(sockfd);
close(sockfd);
}
5. 使用数据库sqlite,将步骤4的信令insert到数据库中qslite操作可以参考下面文章: 《嵌入式数据库sqlite3【基础篇】-基本命令操作,小白一看就懂》 6. 用C语言执行步骤5的数据库操作指令,并将代码合并到步骤4的架构中C语言操作数据库,可以参考:《如何用C语言操作sqlite3,一文搞懂》 7. 用任意一款抓包工具抓取一个ip数据包,保存到数组frm[]
拷贝出数据: 80 8F 1D C7 A6 07 D8 BB C1 C8 51 C3 08 00 45 00 00 34 FC 6E 40 00 80 06 00 00 C0 A8 00 6B 8E FA C4 CA 21 AD 01 BB 25 C1 79 D5 00 00 00 00 80 02 FA F0 14 FF 00 00 02 04 05 B4 01 03 03 08 01 01 04 02
转换成数组: unsigned char frm[]={
0x80,0x8F,0x1D,0xC7,0xA6,0x07,0xD8,0xBB,0xC1,0xC8,0x51,0xC3,0x08,0x00,0x45,0x00,0x00,0x34,0xFC,0x6E,0x40,
0x00,0x80,0x06,0x00,0x00,0xC0,0xA8,0x00,0x6B,0x8E,0xFA,0xC4,0xCA,0x21,0xAD,0x01,0xBB,0x25,0xC1,0x79,0xD5,
0x00,0x00,0x00,0x00,0x80,0x02,0xFA,0xF0,0x14,0xFF,0x00,0x00,0x02,0x04,0x05,0xB4,0x01,0x03,0x03,0x08,0x01,
0x01,0x04,0x02
};
8. 提取出ip数据包的mac头,ip数据包的ip头注意:字节序问题 mact头提取:
#define MAC_FMG "%02x:%02x:%02x:%02x:%02x:%02x\n"
#define printfmac(x) printf(MAC_FMG,x[0],x[1],x[2],x[3],x[4],x[5])
struct mac_h{
u8 dst[6];
u8 src[6];
u16 pro;
};
int parse_mac_h(u8 *data,struct mac_h *pmac_h,int len)
{
int pos = 0;
if(len<6+6+2)
{
return -1;
}
pos = 0;
memcpy(pmac_h->dst,&data[pos],6);
pos+=6;
memcpy(pmac_h->src,&data[pos],6);
pos+=6;
pmac_h->pro = data[pos]<<8 | data[pos+1];
pos+=2;
}
int main()
{
struct mac_h mac_header;
......
parse_mac_h(frm,&mac_header,sizeof(frm));
......
return 1;
}
执行结果如下: 
ip头: #define IPADDR_FMG "%d.%d.%d.%d\n"
#define printipaddr(x) printf(IPADDR_FMG,((u8*)&(x))[0],((u8*)&(x))[1],((u8*)&(x))[2],((u8*)&(x))[3])
void dump_iphdr(struct iphdr *iph)
{
printf("ihl:%d\nversion:%d\ntos:%d\ntot_len:%x\nid:%x\nfrag_off:%x\nttl:%d\nprotocol:%d\ncheck:%x\n",
iph->ihl,
iph->version,
iph->tos,
iph->tot_len,
iph->id,
iph->frag_off,
iph->ttl,
iph->protocol,
iph->check
);
printipaddr(iph->saddr);
printipaddr(iph->daddr);
}
int parse_iphdr(u8 *data,struct iphdr *iph,int len)
{
int pos = 0;
iph->ihl = data[pos]&0xf;
iph->version = data[pos]>>4;
pos+=1;
iph->tos = data[pos];
pos+=1;
getdata16(&iph->tot_len,&data[pos]);
pos+=2;
getdata16(&iph->id,&data[pos]);
pos+=2;
getdata16(&iph->frag_off,&data[pos]);
pos+=2;
iph->ttl = data[pos];
pos+=1;
iph->protocol = data[pos];
pos+=1;
getdata16(&iph->check,&data[pos]);
pos+=2;
getdata32(&iph->saddr,&data[pos]);
pos+=4;
getdata32(&iph->daddr,&data[pos]);
pos+=4;
}

|