1.client(发送数据包)(需要校验和)
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: client.c
**
** 创 建 人: zhangyazhong(张亚中)
**
** 文件创建日期: 2018 年 07 月 19日
**
** 描 述: 自定义协议头客户端程序.
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if_ether.h>
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
#define BUFSIZE 38
#define TTLSET 255
#define IPVERSION 4
#define DEST_PORT 8101
#define SRC_PORT 880
#define errorlog(msg) do{ \
printf(msg);\
exit(1); \
}while(0)
/*********************************************************************************************************
结构体定义
*********************************************************************************************************/
//typedef struct iphdr{
// unsigned int ip_length:4; /*little-endian*/
// unsigned int ip_version:4;
// unsigned char ip_tos;
// unsigned short ip_total_length;
// unsigned short ip_id;
// unsigned short ip_flags;
// unsigned char ip_ttl;
// unsigned char ip_protocol;
// unsigned short ip_cksum;
// unsigned int ip_source;
// unsigned int ip_dest;
//}iphdr;
typedef struct udphdr{
unsigned short udp_sport;
unsigned short udp_dport;
unsigned short udp_ulength;
unsigned short udp_chksum;
}udphdr;
typedef struct udpvhdr{
unsigned int udpv_src;
unsigned int udpv_dest;
unsigned char udpv_memzero;
unsigned char udpv_proto;
unsigned short udpv_vlength;
}udpvhdr;
/*********************************************************************************************************
全局变量定义
*********************************************************************************************************/
char datapacket[BUFSIZE] = {0};
/*********************************************************************************************************
** 函数名称: udp_chsum
** 功能描述:
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
API 函数
*********************************************************************************************************/
unsigned short udpv_hdr_data_chk(unsigned short *addr, int len)
{
unsigned long chksum = 0;
while(len > 1){
chksum += *addr++;
len -= sizeof(unsigned short);
}
if(len){
chksum = chksum + *(unsigned char *)addr;
}
chksum = (chksum >> 16) + (chksum & 0xfffful);
chksum += (chksum >>16);
return (unsigned short )(~chksum);
}
/*********************************************************************************************************
** 函数名称: iphdr_fill
** 功能描述: 构造 IP 头
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
API 函数
*********************************************************************************************************/
void iphdr_fill(struct ip *iphdr, struct sockaddr_in *src, struct sockaddr_in *dest, unsigned short ulen, unsigned char tos, unsigned char id)
{
iphdr->ip_hl = 5;
iphdr->ip_v= 4;
iphdr->ip_tos = tos;
iphdr->ip_len = htons(sizeof(datapacket));
iphdr->ip_id = id;
iphdr->ip_off = 0x40;
iphdr->ip_ttl = 0x40;
iphdr->ip_p = 0x11;
iphdr->ip_sum = 0;
iphdr->ip_src = src->sin_addr;
iphdr->ip_dst = dest->sin_addr;
// iphdr->ip_cksum = udpv_hdr_data_chk((unsigned short*)datapacket, 20);
}
/*********************************************************************************************************
** 函数名称: udphdr_fill
** 功能描述: 构造 UDP 头
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
API 函数
*********************************************************************************************************/
void udphdr_fill(struct udphdr *udph, struct sockaddr_in *src, struct sockaddr_in *dest, unsigned short ulen)
{
udph->udp_chksum = 0;
udph->udp_dport = htons(DEST_PORT);
udph->udp_sport = htons(8000);
udph->udp_ulength = htons(ulen);
}
/*********************************************************************************************************
** 函数名称: udp_header_ctor
** 功能描述: 构造 UDP 头
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
API 函数
*********************************************************************************************************/
void udpvhdr_fill(struct udpvhdr *udpv, unsigned int src, unsigned int dest, unsigned char zero, unsigned char proto, unsigned short udphp)
{
udpv->udpv_dest = dest;
udpv->udpv_memzero = zero;
udpv->udpv_src = src;
udpv->udpv_proto = proto;
udpv->udpv_vlength = udphp;
}
/*********************************************************************************************************
** 函数名称: send_packet
** 功能描述:
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
API 函数
*********************************************************************************************************/
void send_data(int fd, struct sockaddr_in *client, struct sockaddr_in *server)
{
int tos;
int tostmp = 0;
int id = 0;
int i = 0;
memset(datapacket, 'a', sizeof(datapacket) - 1);
for(i = 0; i < 50; i++){
struct ip *iphdr;
udphdr *udph;
udpvhdr udpv;
tos = tostmp;
iphdr = (struct ip *)datapacket;
udph = (struct udphdr *)(datapacket + 20);
iphdr_fill(iphdr, client, server, sizeof(datapacket), tos, id);
udphdr_fill(udph, client, server, sizeof(datapacket) - 20);
udpvhdr_fill(&udpv,client->sin_addr.s_addr, server->sin_addr.s_addr, 0, 0x11, udph->udp_ulength);
char ckbuf[sizeof(udpv) + ntohs(udph->udp_ulength)];/*new packet for check*/
memcpy(ckbuf, &udpv, sizeof(udpv));
memcpy(ckbuf + sizeof(udpv), datapacket + 20, sizeof(datapacket) - 20);
udph->udp_chksum = udpv_hdr_data_chk((unsigned short *)ckbuf, sizeof(ckbuf));
sendto(fd, datapacket, sizeof(datapacket), 0, (struct sockaddr *)server, sizeof(struct sockaddr_in));
sleep(1);
}
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char **argv)
{
int sockfd;
int flag = 1;
struct sockaddr_in serveraddr, clientaddr;
if(argc < 3){
errorlog("argument too less\n");
}
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if(sockfd <0){
errorlog("fail to socket\n");
}
// char *src, *dest;
// src = argv[1];
// dest = argv[2];
bzero(&serveraddr, sizeof(serveraddr)); /*clear serveraddr*/
/*server fill*/
serveraddr.sin_family = AF_INET;
// serveraddr.sin_len = socklen;
serveraddr.sin_port = htons(DEST_PORT);
// serveraddr.sin_addr.s_addr = inet_addr(dest);
serveraddr.sin_addr.s_addr = inet_addr(argv[2]);
/*client fill*/
clientaddr.sin_addr.s_addr = inet_addr(argv[1]);
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (void *)&flag, sizeof(flag)); /*ipheader change*/
send_data(sockfd, &clientaddr, &serveraddr);
close(sockfd);
return (0);
}
2.server(需绑定)
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/udp.h>
#include <time.h>
#include <sys/time.h>
#define __BUF_SIZE 1024
#define LocalPort 8101
#define errorlog(msg) do{ \
perror(msg); \
exit(1); \
}while(0)
int main (int argc, char **argv)
{
int sockFd;
int iRet;
int getRet;
struct sockaddr_in localaddr;
socklen_t socklen = sizeof(localaddr);
char localbuf[__BUF_SIZE] = {0};
struct timeval start, end, result;
if (argc < 2) {
errorlog("argument too less\n");
}
sockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockFd < 0) {
errorlog("socket failed\n");
}
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(LocalPort);
if (argv[1]) {
if (inet_aton(argv[1], &localaddr.sin_addr) == 0) {
errorlog("arguments error\n");
}
} else {
errorlog("can not found addr\n");
}
localaddr.sin_len = socklen;
iRet = bind(sockFd, (struct sockaddr *)&localaddr, socklen);
if (iRet < 0) {
errorlog("bind error\n");
}
while (1) {
bzero(localbuf, sizeof(localbuf));
gettimeofday(&start, NULL);
getRet = recvfrom(sockFd, localbuf, __BUF_SIZE, 0, (struct sockaddr *)&localaddr, &socklen);
gettimeofday(&end, NULL);
if (getRet < 0) {
errorlog("recvfrom failed\n");
} else if(getRet == 0) {
printf("NO DATA get\n");
} else {
timersub(&end, &start, &result);
printf("localbuf = %s (time: %lld.%ld)\n", localbuf, result.tv_sec, result.tv_usec);
}
}
close(sockFd);
return (0);
}