一、传输层socket(四层socket,普通socket)

可参考本人以下博客:

Windows Socket编程之UDP实现大文件的传输:http://blog.csdn.net/luchengtao11/article/details/71016222

Windows Socket编程之TCP实现大文件的传输:http://blog.csdn.net/luchengtao11/article/details/71012580

(1)创建

  1.  
    socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//TCP
  2.  
    //或者
  3.  
    socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);//UDP

AF_INEF表示TCP/IP族

第三个参数可以为0,由操作系统自行选择

(2)发送

  sendto(sd,buffer,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));//UDP
 
  send(sd, buffer, BUFSIZ, 0);  //TCP
 

(3)接收

recvfrom(sd,buffer,BUFSIZ,0,(SOCKADDR*)&addrClient,sizeof(SOCKADDR));//UDP
 
recv(sd, buffer, BUFSIZ, 0);//TCP
 

sd为socket标识符,buffer为接受/发送缓冲区,BUFSIZ为接受/发送缓冲区。后两个参数为发送或接受的对方地址,可以为NULL

二、网络层socket(三层socket)

可以参考本人一下博客或代码:

Linux下的raw Socket(原始套接字)编程:http://blog.csdn.net/luchengtao11/article/details/73878760

网络层多线程收发:https://github.com/Wuchenwcf/MyCode/blob/master/C%2B%2B/Linux/computer%20network/raw_socket_%E7%BD%91%E7%BB%9C%E5%B1%82%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%94%B6%E5%8F%91.cpp

(1)创建

socket(AF_INET, SOCK_RAW, IPPROTO_UDP );//第三个参数可以是UDP,TCP或者ICMP
 

(2)接收

recvfrom(sd, buffer, sizeof(buffer), 0,(struct sockaddr *)&client_addr, &addrlen));// 
 

后两个参数可以为null

接受的报文是从IP数据报的第一个字节开始的。

当内核有一个需要传递到原始套接字的IP数据报时,它将检查所有进程上的原始套接字,以寻找所有匹配的套接字。每个匹配懂得套接字将被递送以该iP数据报的一个副本。(事实证明,如果进程过多,匹配的套接字过多,内核会忙于数据报的软过滤和分发,而实际的套接字却空闲,导致性能下降)
内核对每个原始套接字均执行如下3个测试,只有这三个测试为真,内核才把接收到的数据报递送到这个套接字。

【1】如果创建这个套接字时制订了非0的协议参数(socket的第三个参数),那么接受到的数据报的协议字段必须匹配该值,否则数据报不递送到这个套接字

【2】如果这个原始套接字已由bind调用绑定了某个本地IP地址,那么接受到的数据报的目的IP地址必须匹配这个绑定的地址,否则该数据报不递送到这个套接字。

【3】如果这个原始套接字已由connect调用指定了某个外地IP地址,那么接受到的数据报的源IP地址必须匹配这个已连接地址,否则该数据报不递送到这个套接字。

注意,如果一个原始套接字以0值协议参数创建的,而且没有bind和connect,那么该套接字将接收可由内核传递到原始套接字的每个原始数据报的一个副本。

(3)发送

  1.  
    /*
  2.  
    如果IP_HDRINCL未开启,由进程让内核发送的数据是从IP首部之后的第一个字节开始的,内核会自动构造合适的IP
  3.  
    如果IP_HDRINGL开启,进程需要自行构造IP包
  4.  
    */
  5.  
    /*
  6.  
    if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(int)))
  7.  
    {
  8.  
    perror("setsockopt() error");
  9.  
    exit(-1);
  10.  
    }
  11.  
    */
  12.  
    sendto(sd, buffer, request_length, 0, (sockaddr *)&client_addr, addrlen);

三、数据链路层scoket(二层socket)

代码可以参考:

raw_socket_数据链路层收发实例:https://github.com/Wuchenwcf/MyCode/blob/master/C%2B%2B/Linux/computer%20network/raw_socket_%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82%E6%94%B6%E5%8F%91%E5%AE%9E%E4%BE%8B.cpp

(1)创建

sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));//第三个参数可以为ETH_P_ALL ETH_P_IP ETH_P_ARP等
 

(2)接受

  1.  
    struct sockaddr_ll client;
  2.  
    socklen_t addr_length = sizeof(sockaddr_ll);
  3.  
    recvfrom(sock, buffer, 2048, 0, (sockaddr *)&client, &addr_length);//此时的地址是数据链路层的地址

接受的报文是从以太网的帧开始的

(3)发送

sendto(sock, sendbuffer, n, 0, (struct sockaddr *) &client, sizeof(client));
 

四、小结

引用:http://blog.csdn.net/firefoxbug/article/details/7561159

网卡对该数据帧进行硬过滤(根据网卡的模式不同会有不同的动作,如果设置了promisc混杂模式的话,则不做任何过滤直接交给下一层输入例程,否则非本机mac或者广播mac会被直接丢弃).按照上面的例子,如果成功的话,会进入ip输入例程.但是在进入ip输入例程之前,系统会检查系统中是否有通过socket(AF_PACKET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要ETH_P_IP或者ETH_P_ALL类型.系统就给每个这样的socket接收缓冲区发送一个数据帧拷贝.然后进入下一步.

其次,进入了ip输入例程(ip层会对该数据包进行软过滤,就是检查校验或者丢弃非本机ip或者广播ip的数据包等,具体要参考源代码),例子中就是如果成功的话会进入udp输入例程.但是在交给udp输入例程之前,系统会检查系统中是否有通过socket(AF_INET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要IPPROTO_UDP类型.系统就给每个这样的socket接收缓冲区发送一个数据帧拷贝.然后进入下一步。

最后,进入udp输入例程 ...

ps:如果校验和出错的话,内核会直接丢弃该数据包的.而不会拷贝给sock_raw的套接字,因为校验和都出错了,数据肯定有问题的包括所有信息都没有意义了.

raw_socket(原始套接字)以及普通socket使用终极总结的更多相关文章

  1. Raw Socket(原始套接字)实现Sniffer(嗅探)

    参考资料: https://www.xuebuyuan.com/3190946.html https://blog.csdn.net/zxygww/article/details/52093308 i ...

  2. linux原始套接字(2)-icmp请求与接收

    一.概述                                                    上一篇arp请求使用的是链路层的原始套接字.icmp封装在ip数据报里面,所以icmp请 ...

  3. Go中原始套接字的深度实践

    1. 介绍 2. 传输层socket 2.1 ICMP 2.2 TCP 2.3 传输层协议 3. 网络层socket 3.1 使用Go库 3.2 系统调用 3.3 网络层协议 4. 总结 4.1 参考 ...

  4. 原始套接字-自定义IP首部和TCP首部

    /* ===================================================================================== * * Filenam ...

  5. 原始套接字--简易ping程序

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> ...

  6. Linux基础(11)原始套接字

    一边接收函数返回一边判断返回值时一定要把接收的优先级加()提高再去判断 例 if((sockfd = socket()) < 0) 问题: 如何实现SYN扫描器扫描端口 , 比如AB两个设备要进 ...

  7. Linux Socket 原始套接字编程

    对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...

  8. Linux系统编程(37)—— socket编程之原始套接字

    原始套接字的特点 原始套接字(SOCK_RAW)可以用来自行组装IP数据包,然后将数据包发送到其他终端.也就是说原始套接字是基于IP数据包的编程(SOCK_PACKET是基于数据链路层的编程).另外, ...

  9. 《Python黑帽子:黑客与渗透测试编程之道》 网络:原始套接字和流量嗅探

    Windows和Linux上的包嗅探: #!/usr/bin/python import socket import os #监听的主机 host = "10.10.10.160" ...

随机推荐

  1. Python最佳学习路线图

    python语言基础(1)Python3入门,数据类型,字符串(2)判断/循环语句,函数,命名空间,作用域(3)类与对象,继承,多态(4)tkinter界面编程(5)文件与异常,数据处理简介(6)Py ...

  2. windows下sublime通过sftp扩展上传文件到linux服务器上

    首先在package controll下载sftp扩展,在任意磁盘下新建文件夹: 然后,添加该文件夹到sublime中,并在xhell中链接linux服务器,新建目录,mkdir  /home/hel ...

  3. tyvj1051 选课

    /* 分组背包+树形dp:以树的深度作为阶段,以节点编号作为一维状态, 思路:首先dp[u][t]表示选择以第u门课为根,选了t门课的最大值, 状态转移方程dp[u][t]=max(所有儿子中凑出t- ...

  4. Paget Object 设计模式编写selenium测试用例

    示例常规代码 baidu.py # _*_ coding:utf-8 _*_ import csv,unittest,time #导入csv模块 from time import sleep from ...

  5. JS基础:(一)

    开发了很多项目,感觉javascript脚本语言用处太大了,所以,把一些心得写出来,尤其是调试的技巧. 本次开发工具:Webstorm 1.  官网:http://www.jetbrains.com/ ...

  6. Android使用帧动画内存溢出解决方法

    Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...

  7. 微服务的发现与注册--Eureka

    目录 服务提供者.服务消费者.服务发现组件三者之间的关系 Eureka 简介 Eureka Server Eureka Client 编写Eureka Server 将微服务注册到Eureka Ser ...

  8. [SDOI2012]拯救小云公主

    题解: 是一个不错的题目 首先我们可以考虑二分答案 然后变成判定性问题 对于每个画一个圆 当其会被阻断时就是答案 阻断有四种情况 左下 上下 左右 右上 但是这样是n^2a(n)*logn的 考虑直接 ...

  9. Educational Codeforces Round 26-D. Round Subset

    题目大意:给你n个数字(小于1e18),从n个数中取k个数字相乘,使其后缀0最多,问你后缀0最多是多少. 知道得用三维的dp[ i ] [ j ] [ k ]  第一维表示用到第 i 个数为止,j 表 ...

  10. Python swapcase

    swapcase 字符串大写转换为小写小写转换为大写. a = "woHaoshuai" a.swapcase() WOhAOSHUAI