不使用ip和port如何进行网络通讯(raw socket应用例子)

主要应用方向是上位机和嵌软(如stm32单片机)通讯,不在单片机中嵌入web server,即mac层通讯。

一、下面先了解网络数据包组成。

常见数据包的包头长度:

EtherHeader Length: 14 Bytes
TCP Header Length  : 20 Bytes
UDP Header Length  : 8  Bytes
IP Header Length   : 20 Bytes

1.网络封包的整体过程

e1b0c771a17e54f94f62d9352f460fbb.jpeg

2.IP 数据包

d5ec72b3e4f6f28583b0cdd162138313.jpeg

3.Tcp 数据包

80969a758ec2fd198eeb326842e12eb6.jpeg23965430bc44ca5a4d5b5e23a24faca9.jpeg

4.UDP 数据包

a9e3e4d19af42858d2b3b506fc51d260.jpeg

ecf6eea13316122ee343071b633b9f83.jpeg

5、Ethernet Header:

b88ec2a87ce65d370a32fd07cdebf61b.jpeg

6、ICMP Packet:

cbc3c93586a7633e20790351c2d5671c.jpeg

9344c7835545c76e5895db4bce705ceb.jpeg

7、ARP Packet:

b5b485eaa7678c7e5c59129e2d114a92.jpeg

二、程序接收报文示例

*************************UDP Packet******************************
Ethernet Header
  |-Source Address  : 00-0C-29-64-D9-F5
  |-Destination Address  : FF-FF-FF-FF-FF-FF
  |-Protocol    : 8


IP Header
  |-Version              : 4
  |-Internet Header Length  : 5 DWORDS or 20 Bytes
  |-Type Of Service   : 16
  |-Total Length      : 33  Bytes
  |-Identification    : 10201
  |-Time To Live      : 64
  |-Protocol       : 17
  |-Header Checksum   : 37369
  |-Source IP         : 0.0.0.0
  |-Destination IP    : 192.168.0.66


UDP Header
  |-Source Port      : 23451
  |-Destination Port  : 23452
  |-UDP Length        : 13
  |-UDP Checksum     : 0


Data
 AA  BB  CC  DD  EE  00  00  00  00  00  00  00  00  00  00  00 
 00  00  00  00  00  00 
*****************************************************************

三、程序示例

程序环境:ubuntu 14.04 send(虚拟机,自定义模式 VMnet1)

                 Ubuntu 16.04 recv(虚拟机,自定义模式 VMnet1)

1、send

int main()
{
  sock_raw=socket(AF_PACKET,SOCK_RAW,IPPROTO_RAW);
  if(sock_raw == -1)
    printf("error in socket");


        // increase in case of large data.Here data is --> AA  BB  CC  DD  EE
  sendbuff=(unsigned char*)malloc(64); 
  memset(sendbuff,0,64);




        get_eth_index();  // interface number
        get_mac();
        get_ip();


  struct sockaddr_ll sadr_ll;
//        sadr_ll.sll_ifindex = ifreq_i.ifr_ifindex;
        sadr_ll.sll_ifindex = if_nametoindex("eth0");
  sadr_ll.sll_halen   = ETH_ALEN;
  sadr_ll.sll_addr[0]  = DESTMAC0;
  sadr_ll.sll_addr[1]  = DESTMAC1;
  sadr_ll.sll_addr[2]  = DESTMAC2;
  sadr_ll.sll_addr[3]  = DESTMAC3;
  sadr_ll.sll_addr[4]  = DESTMAC4;
  sadr_ll.sll_addr[5]  = DESTMAC5;


  printf("sending...\n");
  while(1)
  {
  send_len = sendto(sock_raw,sendbuff,64,0,(const struct sockaddr*)&sadr_ll,sizeof(struct sockaddr_ll));
    if(send_len<0)
    {
      printf("error in sending....sendlen=%d....errno=%d\n",send_len,errno);
      return -1;
    }
  }
}

2、recv

/* Note: run this program as root user
 * Author:Subodh Saxena 
 */
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<signal.h>
#include<stdbool.h>
#include<sys/socket.h>
#include<sys/types.h>


#include<linux/if_packet.h>
#include<netinet/in.h>     
#include<netinet/if_ether.h>    // for ethernet header
#include<netinet/ip.h>    // for ip header
#include<netinet/udp.h>    // for udp header
#include<netinet/tcp.h>
#include<arpa/inet.h>           // to avoid warning at inet_ntoa


FILE* log_txt;
int total,tcp,udp,icmp,igmp,other,iphdrlen;


struct sockaddr saddr;
struct sockaddr_in source,dest;


void ethernet_header(unsigned char* buffer,int buflen)
{
  struct ethhdr *eth = (struct ethhdr *)(buffer);
  fprintf(log_txt,"\nEthernet Header\n");
  fprintf(log_txt,"\t|-Source Address  : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
  fprintf(log_txt,"\t|-Destination Address  : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
  fprintf(log_txt,"\t|-Protocol    : %d\n",eth->h_proto);


}


void ip_header(unsigned char* buffer,int buflen)
{
  struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr));


  iphdrlen =ip->ihl*4;


  memset(&source, 0, sizeof(source));
  source.sin_addr.s_addr = ip->saddr;     
  memset(&dest, 0, sizeof(dest));
  dest.sin_addr.s_addr = ip->daddr;     


  fprintf(log_txt , "\nIP Header\n");


  fprintf(log_txt , "\t|-Version              : %d\n",(unsigned int)ip->version);
  fprintf(log_txt , "\t|-Internet Header Length  : %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4);
  fprintf(log_txt , "\t|-Type Of Service   : %d\n",(unsigned int)ip->tos);
  fprintf(log_txt , "\t|-Total Length      : %d  Bytes\n",ntohs(ip->tot_len));
  fprintf(log_txt , "\t|-Identification    : %d\n",ntohs(ip->id));
  fprintf(log_txt , "\t|-Time To Live      : %d\n",(unsigned int)ip->ttl);
  fprintf(log_txt , "\t|-Protocol       : %d\n",(unsigned int)ip->protocol);
  fprintf(log_txt , "\t|-Header Checksum   : %d\n",ntohs(ip->check));
  fprintf(log_txt , "\t|-Source IP         : %s\n", inet_ntoa(source.sin_addr));
  fprintf(log_txt , "\t|-Destination IP    : %s\n",inet_ntoa(dest.sin_addr));
}


void payload(unsigned char* buffer,int buflen)
{
  int i=0;
  unsigned char * data = (buffer + iphdrlen  + sizeof(struct ethhdr) + sizeof(struct udphdr));
  fprintf(log_txt,"\nData\n");
  int remaining_data = buflen - (iphdrlen  + sizeof(struct ethhdr) + sizeof(struct udphdr));
  for(i=0;i<remaining_data;i++)
  {
    if(i!=0 && i%16==0)
      fprintf(log_txt,"\n");
    fprintf(log_txt," %.2X ",data[i]);
  }


  fprintf(log_txt,"\n");






}


void tcp_header(unsigned char* buffer,int buflen)
{
  fprintf(log_txt,"\n*************************TCP Packet******************************");
     ethernet_header(buffer,buflen);
    ip_header(buffer,buflen);


     struct tcphdr *tcp = (struct tcphdr*)(buffer + iphdrlen + sizeof(struct ethhdr));
     fprintf(log_txt , "\nTCP Header\n");
     fprintf(log_txt , "\t|-Source Port          : %u\n",ntohs(tcp->source));
     fprintf(log_txt , "\t|-Destination Port     : %u\n",ntohs(tcp->dest));
     fprintf(log_txt , "\t|-Sequence Number      : %u\n",ntohl(tcp->seq));
     fprintf(log_txt , "\t|-Acknowledge Number   : %u\n",ntohl(tcp->ack_seq));
     fprintf(log_txt , "\t|-Header Length        : %d DWORDS or %d BYTES\n" ,(unsigned int)tcp->doff,(unsigned int)tcp->doff*4);
  fprintf(log_txt , "\t|----------Flags-----------\n");
  fprintf(log_txt , "\t\t|-Urgent Flag          : %d\n",(unsigned int)tcp->urg);
  fprintf(log_txt , "\t\t|-Acknowledgement Flag : %d\n",(unsigned int)tcp->ack);
  fprintf(log_txt , "\t\t|-Push Flag            : %d\n",(unsigned int)tcp->psh);
  fprintf(log_txt , "\t\t|-Reset Flag           : %d\n",(unsigned int)tcp->rst);
  fprintf(log_txt , "\t\t|-Synchronise Flag     : %d\n",(unsigned int)tcp->syn);
  fprintf(log_txt , "\t\t|-Finish Flag          : %d\n",(unsigned int)tcp->fin);
  fprintf(log_txt , "\t|-Window size          : %d\n",ntohs(tcp->window));
  fprintf(log_txt , "\t|-Checksum             : %d\n",ntohs(tcp->check));
  fprintf(log_txt , "\t|-Urgent Pointer       : %d\n",tcp->urg_ptr);


  payload(buffer,buflen);


fprintf(log_txt,"*****************************************************************\n\n\n");
}


void udp_header(unsigned char* buffer, int buflen)
{
  fprintf(log_txt,"\n*************************UDP Packet******************************");
  ethernet_header(buffer,buflen);
  ip_header(buffer,buflen);
  fprintf(log_txt,"\nUDP Header\n");


  struct udphdr *udp = (struct udphdr*)(buffer + iphdrlen + sizeof(struct ethhdr));
  fprintf(log_txt , "\t|-Source Port      : %d\n" , ntohs(udp->source));
  fprintf(log_txt , "\t|-Destination Port  : %d\n" , ntohs(udp->dest));
  fprintf(log_txt , "\t|-UDP Length        : %d\n" , ntohs(udp->len));
  fprintf(log_txt , "\t|-UDP Checksum     : %d\n" , ntohs(udp->check));


  payload(buffer,buflen);


  fprintf(log_txt,"*****************************************************************\n\n\n");






}


void data_process(unsigned char* buffer,int buflen)
{
  struct iphdr *ip = (struct iphdr*)(buffer + sizeof (struct ethhdr));
  ++total;
  /* we will se UDP Protocol only*/ 
  switch (ip->protocol)    //see /etc/protocols file 
  {


    case 6:
      ++tcp;
//      tcp_header(buffer,buflen);
      break;


    case 17:
      ++udp;
      udp_header(buffer,buflen);
      break;


    default:
      ++other;


  }
  printf("TCP: %d  UDP: %d  Other: %d  Toatl: %d  \r",tcp,udp,other,total);




}






int main()
{


  int sock_r,saddr_len,buflen;


  unsigned char* buffer = (unsigned char *)malloc(65536); 
  memset(buffer,0,65536);


  log_txt=fopen("log.txt","w");
  if(!log_txt)
  {
    printf("unable to open log.txt\n");
    return -1;


  }


  printf("starting .... \n");


  sock_r=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); 
  if(sock_r<0)
  {
    printf("error in socket\n");
    return -1;
  }


  while(1)
  {
    saddr_len=sizeof saddr;
    buflen=recvfrom(sock_r,buffer,65536,0,&saddr,(socklen_t *)&saddr_len);




    if(buflen<0)
    {
      printf("error in reading recvfrom function\n");
      return -1;
    }
    fflush(log_txt);
    data_process(buffer,buflen);


  }


  close(sock_r);// use signals to close socket 
  printf("DONE!!!!\n");


}

如需完成发送程序,可关注公众号后,后台留言,说明所需程序。

欢迎关注公众号:

ad250838283e2f726b67e3a9ddb17687.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值