socket()函数介绍

socket()函数介绍

函数原型:

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

函数功能:

创建套接字:应用程序在使用套接字前,首先必须用于一个套接字,系统调用socket()向应用程序提供新建的套接字。

参数说明:

1. domain:即协议域,又称为协议族(family), 常用的协议族有,AF_INET (IPV4)/ AF_INET6(IPV6)/ AF_LOCAL(或称AF_UNIX) / AF_ROUTE等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如 AF_INET 决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。对于TCP/IP协议族,该参数设置为AF_INET;

2. type:套接字类型。

TCP/IP的socket提供下列3种类型套接字。

流式套接字(SOCK_STREAM):需要双方建立可行的数据连接后才能通信。

数据报式套接字(SOCK_DGRAM):只是简单的将数据阿松到对应的目的主机即可,而不管对方是都处于存活状态,对方是否允许以及该数据包是否完整的被发送到目标主机。

原始式套接字(SOCK_RAW):该接口允许对较低层协议,如IP / ICMP直接访问。常用于检验新的协议实现或者访问现有服务中配置的新设备。

3. protocol: 指定应用程序所使用的通信协议。此参数可以执行单个协议系列中的不同传输协议。在Internet通讯域中,此参数一般取值为0,系统会根据套接字的类型决定应使用的传输层协议。

函数返回值:

成功:返回新创建套接字描述符;

失败:返回-1,错误码在error中。

其他协议族补充:

PF_NETLINK

Netlink socket 是一种Linux特有的socket,用于实现用户进程与内核进程之间通信的一种特殊的进程间通信方式(IPC) ,也是网络应用程序与内核通信的最常用的接口。
  Netlink 是一种在内核和用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就能使用 Netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 Netlink。Android udev机制就是采用的PF_NETLINK.

原文链接:https://blog.csdn.net/jmflovezlf/article/details/41935099

 AF_NETLINK 或 PF_NETLINK,在 Linux 中,它们俩实际为一个东西,它表示要使用netlink,第二个参数必须是SOCK_RAW或SOCK_DGRAM, 第三个参数指定netlink协议类型,可以是自己在netlink.h中定义的,也可以是内核中已经定义好的。上面的例子使用主要是路由的Netlink协议。也可以是上面21中协议类型的其中之一。

NETLINK_GENERIC是一个通用的协议类型,它是专门为用户使用的,因此,用户可以直接使用它,而不必再添加新的协议类型。

对于每一个netlink协议类型,可以使用多播的概念,最多可以有 32个多播组,每一个多播组用一个位表示,netlink 的多播特性使得发送消息给同一个组仅需要一次系统调用,因而对于需要多播消息的应用而言,大大地降低了系统调用的次数。

原文链接:https://blog.csdn.net/zcabcd123/article/details/8272423

 PF_PACKET:

在linux中提供了PF_PACKET接口可以操作链路层的数据。
定义一个pf_packet = socket(PF_SOCKET, SOCK_RAW, htons(ETH_P_RARP));
就可以利用函数sendto和recefrom来读取和发送链路层的数据包了(当然,发送ARP包,上面第三个参数要变为 htons(ETH_P_ARP),或者IP的包为ETH_P_IP,可查看文件/usr/include/linux/if_ether.h文件看到所有支持的协议)。

原文链接:https://www.cnblogs.com/cdwodm/archive/2012/09/22/2698163.html

所有链接层的报文,单播、组播、广播,目的MAC地址,IP地址是设备本身配置的,或者是其他设备的,都通过socket发给用户态的抓包、分析程序。

一般链路层在处理收到的报文时,会依据目的MAC、目的IP地址,如果它们不是设备本身配置的(还有一些广播、组播除外),都会丢弃。因此,需要设置设备网络设备为混杂模式(promiscuous)。
原文链接:https://blog.csdn.net/somyjun/article/details/84589579

 

socket是基于tcp/ip的网络编程接口,用于收发数据报,设置接收内核的某些状态以及事件。pf_packet类型的socket,是用来与驱动层面收发数据报的,接收和发送报文包含链路层信息

 

发送接收以太网数据帧

 

bind()函数介绍

函数原型:int bind(int sockfd, structaddr *addr, int addrlen);

函数功能:用来将指定的socket与对应的网络地址进行绑定。参数socket 为已建好连线socket,每个socket只能与一个端口进行绑定,如果用户不显示的进行绑定,操作系统将会给绑定一个随机的端口。

参数说明:

1.sockfd:标识一个已经连接套接口的描述符、

2.addr:是一个指向sockaddr结构体的指针,标识绑定的本地地址信息,如果是IP信息,则要求IP地址必须为本机IP地址,端口必须为一个未占用的本地端口。

//netlink类型的sockaddr

struct sockaddr_nl
{
sa_family_t nl_family; //协议族
unsigned short nl_pad;
u32 nl_pid;
u32 nl_groups;
};

struct sockaddr只是提供地址类型规范,根据不用的应用,sockaddr 需要选用不用的类型。但是,每一种地址都是有sockaddr_前缀,如IPV4选择的是sockaddr_in。AF_NETLINK 选择的是sockaddr_nl。

3.addrlen:欲绑定的网络地址sockaddr的结构长度。

函数返回值:成功:0;失败:-1;错误原因存于error中。

 recvfrom()函数介绍

 函数原型:

int recvfrom(int sockd, void* buf, int len, unsigned int flags, struct sockaddr* from, int* fromlen);

函数功能:用来由指定的socket接受对方主机传送来的数据。参数socket为已经建好连线的socket,如果利用UDP协议则不需要经过连线操作。

参数说明:

1.sockfd:标识一个套接字的描述符。

2.buf:接收数据缓冲区。

3.len:缓冲区长度

4.flags:调用操作方式,一般设0.

5.from:对方主机的网络地址,结构sockaddr请参考bind()

6.fromlen:对方主机地址sockaddr的结构长度

函数返回值:成功:返回实际传送的字符数;失败:-1;错误原因存于error中。

 

epoll使用

原文链接:https://www.cnblogs.com/xuewangkai/p/11158576.html

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epoll的事件注册函数,epoll_ctl向 epoll对象中添加、修改或者删除感兴趣的事件,返回0表示成功,否则返回–1,此时需要根据errno错误码判断错误类型。

它不同与select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。

epoll_wait方法返回的事件必然是通过 epoll_ctl添加到 epoll中的。

第一个参数是epoll_create()的返回值,第二个参数表示动作,用三个宏来表示:
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:

复制代码
 1 typedef union epoll_data {
 2     void *ptr;
 3     int fd;
 4     __uint32_t u32;
 5     __uint64_t u64;
 6 } epoll_data_t;
 7 
 8 struct epoll_event {
 9     __uint32_t events; /* Epoll events */
10     epoll_data_t data; /* User data variable */
11 };
复制代码

 

events可以是以下几个宏的集合:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

 

posted @ 2022-04-07 11:20  bug快递员  阅读(635)  评论(0编辑  收藏  举报