打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
玩转Linux内核套接字(socket)原理与机制

https://m.toutiao.com/is/RpwrPnJ/?=linux基础知识 

1、套接字基本知识

2、套接字表示方式

套接字socket=(ip地址:端口号),套接字表示方法采用点分十进制的ip地址后面写上端口号,中间用冒号或逗号隔开。每个传输层连接唯一地被通信两的两个端点(两个套接字)所确定。比如IP地址是192.168.2.34,端口号是89,那么对应套接字就是(192.168.2.34:89)。

3、socket在网络当中地位及作用

socket在所有的网络操作系统中是必不可少,而且在所有的网络应用唾弃中也是必不可少。它是网络通信中应用程序对应的进程和网络协议之间的接口。具体套接字在网络系统中地位如下:

套接字在网络系统中作用:

a.socket在协议之上,屏蔽不同网络协议之间的差异;

b.socket是网络编程入口,提供大量系统调用,构成网络程序的主体;

c.在Linux系统中,socket属于文件系统的一部分。

4、套接字接口的种类

Linux支持多种套接字种类,不同的套接字种类称为“地址族”。Linux所支持的部分BSD套接字类型常见如下:

套接字地址族 说明

UNIX UNIX域套接字

INET 通过TCP/IP协议支持的Internet地址族

AX25 Amater radio X25

APPLETALK Appletalk DDP

IPX Novell IPX

X25 X25

Linux所支持的BSD套接字类型

流(stream):提供可靠的双向顺序数据流,可以保证数据不会在传输过程中丢失、破坏或重复出现。流套接字通过INET地址族的TCP协议实现。

数据报(datagram):提供双向的数据传输,但是并不对数据的传输过程中提供担保,意思是说,数据可能会以错误的顺序传递,甚至丢失或破坏。这种类型的套接字通过INET地址族的UDP协议实现。

原始(raw):利用这种类型的套接字,进程可以直接访问底层协议(称为原始)。

可靠发送的消息:和数据报套接字类似,但保证数据被正确传输到目的端。

顺序数据包:和流套接字类似,但数据包大小是固定的。

数据包(packet):并不是标准的BSD套接字类型,它是Linux专有的BSD套接字扩展,可允许进程直接在设备访问数据包。

一、套接字的工作原理

INET套接字就是支持Internet地址族的套接字,它位于TCP之上,BSD套接字之下,这也是能够体现Linux网络模块分层的设计架构思想。INET套接字视图如下:

INET和BSD套接字之间的接口通过Internet地址族套接字操作集进行实现,操作集实际是一组协议操作例程,具体对应内核源码如下:

// Internet地址族套接字操作集(一组协议操作例程)

struct proto_ops {

int family;

struct module *owner;

int (*release) (struct socket *sock);

int (*bind) (struct socket *sock,

struct sockaddr *myaddr,

int sockaddr_len);

int (*connect) (struct socket *sock,

struct sockaddr *vaddr,

int sockaddr_len, int flags);

int (*socketpair)(struct socket *sock1,

struct socket *sock2);

int (*accept) (struct socket *sock,

struct socket *newsock, int flags, bool kern);

int (*getname) (struct socket *sock,

struct sockaddr *addr,

int peer);

__poll_t (*poll) (struct file *file, struct socket *sock,

struct poll_table_struct *wait);

int (*ioctl) (struct socket *sock, unsigned int cmd,

unsigned long arg);

#ifdef CONFIG_COMPAT

int (*compat_ioctl) (struct socket *sock, unsigned int cmd,

unsigned long arg);

#endif

int (*gettstamp) (struct socket *sock, void __user *userstamp,

bool timeval, bool time32);

int (*listen) (struct socket *sock, int len);

int (*shutdown) (struct socket *sock, int flags);

int (*setsockopt)(struct socket *sock, int level,

int optname, char __user *optval, unsigned int optlen);

int (*getsockopt)(struct socket *sock, int level,

int optname, char __user *optval, int __user *optlen);

#ifdef CONFIG_COMPAT

int (*compat_setsockopt)(struct socket *sock, int level,

int optname, char __user *optval, unsigned int optlen);

int (*compat_getsockopt)(struct socket *sock, int level,

int optname, char __user *optval, int __user *optlen);

#endif

void (*show_fdinfo)(struct seq_file *m, struct socket *sock);

int (*sendmsg) (struct socket *sock, struct msghdr *m,

size_t total_len);

/* Notes for implementing recvmsg:

* ===============================

* msg->msg_namelen should get updated by the recvmsg handlers

* iff msg_name != NULL. It is by default 0 to prevent

* returning uninitialized memory to user space. The recvfrom

* handlers can assume that msg.msg_name is either NULL or has

* a minimum size of sizeof(struct sockaddr_storage).

*/

int (*recvmsg) (struct socket *sock, struct msghdr *m,

size_t total_len, int flags);

int (*mmap) (struct file *file, struct socket *sock,

struct vm_area_struct * vma);

ssize_t (*sendpage) (struct socket *sock, struct page *page,

int offset, size_t size, int flags);

ssize_t (*splice_read)(struct socket *sock, loff_t *ppos,

struct pipe_inode_info *pipe, size_t len, unsigned int flags);

int (*set_peek_off)(struct sock *sk, int val);

int (*peek_len)(struct socket *sock);

/* The following functions are called internally by kernel with

* sock lock already held.

*/

int (*read_sock)(struct sock *sk, read_descriptor_t *desc,

sk_read_actor_t recv_actor);

int (*sendpage_locked)(struct sock *sk, struct page *page,

int offset, size_t size, int flags);

int (*sendmsg_locked)(struct sock *sk, struct msghdr *msg,

size_t size);

int (*set_rcvlowat)(struct sock *sk, int val);

};

BSD套接字层通过调用proto_ops结构中相应函数执行对应任务。BSD套接字层向INET套接字层传递socket数据结构直接来代表一个BSD套接字,socket结构数据类型对应内核具体源码如下:

进程在利用套接字进程通信时,采用C/S模型。服务器首先创建一个套接字,并将某个名称绑定到此套接字上面,套接字的名称依赖于套接字的底层地址族。但通常是服务器的本地地址。套接字的名称地址通过sockaddr数据结构指定,具体内核源码如下:

Linux内核源码分析:进程管理专题、内存管理专题、网络协议栈专题、设备驱动专题、文件系统专题、项目实战模块专题。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
linux下bluetooth编程(五)bluetooth与socket
linux下USB设备热插拔如何检测
Windows 下的socket(套接字编程)
Linux下getsockopt/setsockopt 函数说明 - xioahw的专栏 ...
【Linux网络编程】原始套接字编程
linux内核ioctl网络控制框架实现分析
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服