1.TCP RAW服务器
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息----------------------------------------------------------------------------------
**
** 文 件 名: tcp_self_raw_iptcp.c
**
** 创 建 人: zhangyazhong (张亚中)
**
** 文件创建日期: 2018年08月22日
**
** 描 述: TCP RAW 自定义服务器
*********************************************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
/*
* ip首部长度
*/
#define IP_HEADER_LEN sizeof(struct ip)
/*
* tcp首部长度
*/
#define TCP_HEADER_LEN sizeof(struct tcphdr)
/*
* ip首部 + tcp首部长度
*/
#define IP_TCP_HEADER_LEN IP_HEADER_LEN + TCP_HEADER_LEN
/*
* 接收数据缓冲大小
*/
#define BUFFER_SIZE 1024
/*
* ip首部 + tcp首部 + 数据缓冲区大小
*/
#define IP_TCP_BUFF_SIZE IP_TCP_HEADER_LEN + BUFFER_SIZE
/*********************************************************************************************************
** 函数名称: raw_socket_recv
** 功能描述: 原始套接字接收
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void raw_socket_recv()
{
struct ip *ip_header;
struct tcphdr *tcp_header;
int sock_raw_fd, ret_len;
char buf[IP_TCP_BUFF_SIZE];
if ((sock_raw_fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
err_exit("socket()");
/*
* 接收数据
*/
while (1) {
bzero(buf, IP_TCP_BUFF_SIZE);
ret_len = recv(sock_raw_fd, buf, IP_TCP_BUFF_SIZE, 0);
if (ret_len > 0) {
/*
* 取出ip首部
*/
ip_header = (struct ip *)buf;
/*
* 取出tcp首部
*/
tcp_header = (struct tcphdr *)(buf + IP_HEADER_LEN);
if (!strcmp(inet_ntoa(ip_header->ip_src), "192.168.7.11") && ntohs(tcp_header->th_sport) == 5566) {
printf("=======================================\n");
printf("from ip:%s\n", inet_ntoa(ip_header->ip_src));
printf("from port:%d\n", ntohs(tcp_header->th_sport));
/*
* 取出数据
*/
printf("get data from client:%s\n", buf + IP_TCP_HEADER_LEN);
}
}
}
close(sock_raw_fd);
}
/*********************************************************************************************************
** 函数名称: tcp_raw_serverHPacket
** 功能描述: TCP RAW服务器主函数
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int tcp_raw_serverHPacket(void)
{
printf("TCP RAW Server Start############################\n");
/*
* 原始套接字接收
*/
raw_socket_recv();
return 0;
}
2.客户端(发送端)
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息----------------------------------------------------------------------------------
**
** 文 件 名: tcpHeader_Packet_self.c
**
** 创 建 人: zhangyazhong (张亚中)
**
** 文件创建日期: 2018年08月22日
**
** 描 述: TCP RAW自定义发送以太网帧(客户端)
*********************************************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
/* ip首部长度 */
#define IP_HEADER_LEN sizeof(struct ip)
/* tcp首部长度 */
#define TCP_HEADER_LEN sizeof(struct tcphdr)
/* ip首部 + tcp首部长度 */
#define IP_TCP_HEADER_LEN IP_HEADER_LEN + TCP_HEADER_LEN
/*********************************************************************************************************
全局变量定义
*********************************************************************************************************/
char Data[256] = "TCP RAW Client!";/*传输内容*/
/*********************************************************************************************************
** 函数名称: err_exit
** 功能描述: 错误处理函数
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void err_exit(const char *err_msg)
{
perror(err_msg);
exit(1);
}
/*********************************************************************************************************
** 函数名称: fill_ip_header
** 功能描述: 填充ip首部
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
struct ip *fill_ip_header(const char *src_ip, const char *dst_ip, int ip_packet_len)
{
struct ip *ip_header;
ip_header = (struct ip *)malloc(IP_HEADER_LEN);
ip_header->ip_v = IPVERSION;
ip_header->ip_hl = sizeof(struct ip) / 4; /* 这里注意,ip首部长度
是指占多个32位的数量,
4字节=32位,所以除以4*/
ip_header->ip_tos = 0;
ip_header->ip_len = htons(ip_packet_len); /* 整个IP数据报长度,包
括普通数据 */
ip_header->ip_id = 0; /* 让内核自己填充标识位 */
ip_header->ip_off = 0;
ip_header->ip_ttl = MAXTTL;
ip_header->ip_p = IPPROTO_TCP; /* ip包封装的协议类型 */
ip_header->ip_sum = 0; /* 让内核自己计算校验和 */
ip_header->ip_src.s_addr = inet_addr(src_ip); /* 源IP地址 */
ip_header->ip_dst.s_addr = inet_addr(dst_ip); /* 目标IP地址 */
return ip_header;
}
/*********************************************************************************************************
** 函数名称: fill_tcp_header
** 功能描述: 填充tcp首部
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
struct tcphdr *fill_tcp_header(int src_port, int dst_port)
{
struct tcphdr *tcp_header;
tcp_header = (struct tcphdr *)malloc(TCP_HEADER_LEN);
tcp_header->th_sport = htons(src_port);
tcp_header->th_dport = htons(dst_port);
/*
* 同IP首部一样,这里是占32位的字节多少个
*/
tcp_header->th_off = sizeof(struct tcphdr) / 4;
/*
* 发起连接
*/
tcp_header->th_flags = TH_SYN;
tcp_header->th_win = 4096;
tcp_header->th_sum = 0;
return tcp_header;
}
/*********************************************************************************************************
** 函数名称: ip_tcp_send
** 功能描述: 发送ip_tcp报文
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void ip_tcp_send(const char *src_ip, int src_port, const char *dst_ip, int dst_port, const char *data)
{
struct ip *ip_header;
struct tcphdr *tcp_header;
struct sockaddr_in dst_addr;
socklen_t sock_addrlen = sizeof(struct sockaddr_in);
int data_len = strlen(data);
int ip_packet_len = IP_TCP_HEADER_LEN + data_len;
char buf[ip_packet_len];
int sockfd, ret_len, on = 1;
bzero(&dst_addr, sock_addrlen);
dst_addr.sin_family = PF_INET;
dst_addr.sin_addr.s_addr = inet_addr(dst_ip);
dst_addr.sin_port = htons(dst_port);
/*
* 创建tcp原始套接字
*/
if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
err_exit("socket()");
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
err_exit("setsockopt()");
ip_header = fill_ip_header(src_ip, dst_ip, ip_packet_len);
tcp_header = fill_tcp_header(src_port, dst_port);
bzero(buf, ip_packet_len);
memcpy(buf, ip_header, IP_HEADER_LEN);
memcpy(buf + IP_HEADER_LEN, tcp_header, TCP_HEADER_LEN);
memcpy(buf + IP_TCP_HEADER_LEN, data, data_len);
while (1) {
ret_len = sendto(sockfd, buf, ip_packet_len, 0, (struct sockaddr *)&dst_addr, sock_addrlen);
if (ret_len > 0){
printf("sendto() ok!!!\n");
} else {
printf("sendto() failed\n");
}
sleep(2);
}
/*
* 发送报文
*/
close(sockfd);
free(ip_header);
free(tcp_header);
}
/*********************************************************************************************************
** 函数名称: tcpHPacket
** 功能描述: 发送ip_tcp报文入口函数
** 输 入 : NONE
** 输 出 :
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int tcpHPacket(int argc, char *argv[])
{
printf("TCP RAW Client Start###########(by yourself)\n");
printf("srcPort:5566\n "
"srcAddr:192.168.7.11\n"
"dstPort:8444\n"
"dstAddr:192.168.7.33\n"
"data is %s\n", Data);
/*
* 发送ip_tcp报文
*/
ip_tcp_send(SRC_ADDR, SRC_PORT, TCP_SERVER_ADDR, TCP_SERVER_PORT, Data);
return 0;
}