一、传输层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. java 持有对象 ListIterator用法

    package ch07; import java.io.*; import java.util.Iterator; import java.util.LinkedList; import java. ...

  2. Gym100340 线性dp

    //看题解写的 https://blog.csdn.net/sdfzyhx/article/details/51804748#include<bits/stdc++.h> using na ...

  3. 两个inline-block元素上下不对齐,出现错位

    摘要: 声明:此文章为转载(点击查看原文),如有侵权24小时内删除.联系QQ:1522025433. 问题描述:在类似 <div class="ovh"> <h3 ...

  4. 文件中用WriteLine追加内容的两种方法

    if (!Directory.Exists("C:\\testll")) { Directory.CreateDirectory("C:\\testll"); ...

  5. 集合Arraylist的方法的使用和打印

    package chapter090; import java.util.ArrayList;import java.util.List; public class TestList01 { publ ...

  6. 【C++ Primer 第11章】2. 关联容器操作

    练习答案 一.访问元素 关联容器额外类型别名  key_type 此容器类型的关键字类型 mapped_type 每个关键字关联的类型,只 适用于map mapped_type 对于set,与key_ ...

  7. Spring的核心之IoC容器创建对象

    Spring的Ioc容器,是Spring的核心内容: 作用:对象的创建和处理对象的依赖关系. Spring容器创建对象有以下几种方式: 1:调用无参数的构造器 <!-- 默认无参的构造器 --& ...

  8. Ubuntu 16.04 LTS 搭建ftp服务器

    其实我之前搭建好了,但是最近我上来看好像跟没搭建一样呢,于是我从新搭建一遍? 我的ubuntu版本: cat /etc/issue Ubuntu 16.04 LTS \n \l 1.安装vsftpd( ...

  9. STM32的HAL库中的DMA_FLAG_TCIF3_7等几个宏定义的含义

    DMA_FLAG_TCIF0_4就是指DMA的通道0和通道4,DMA_FLAG_TCIF1_5就是指DMA的通道1和通道5,DMA_FLAG_TCIF2_6就是指DMA的通道2和通道6,DMA_FLA ...

  10. asp.net core session的使用

    Session介绍 本文假设读者已经了解Session的概念和作用,并且在传统的.net framework平台上使用过. Asp.net core 1.0好像需要单独安装,在nuget控制台,选择你 ...