`
anders0913
  • 浏览: 90662 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

struct socket 结构详解

阅读更多
    用户使用socket系统调用编写应用程序时,通过一个数字来表示一个socket,所有的操作都在该数字上进行,这个数字称为套接字描述符。在系统调用 的实现函数里,这个数字就会被映射成一个表示socket的结构体,该结构体保存了该socket的所有属性和数据。在内核的协议中实现中,关于表示 socket的结构体,是一个比较复杂的东西,下面一一介绍。
    struct socket。
    这是一个基本的BSD socket,我们调用socket系统调用创建的各种不同类型的socket,开始创建的都是它,到后面,各种不同类型的socket在它的基础上进行 各种扩展。struct socket是在虚拟文件系统上被创建出来的,可以把它看成一个文件,是可以被安全地扩展的。下面是其完整定义:
    struct socket {
        socket_state            state;
        unsigned long           flags;
        const struct proto_ops *ops;
        struct fasync_struct    *fasync_list;
        struct file             *file;
        struct sock             *sk;
        wait_queue_head_t       wait;
        short                   type;
    };

    state用于表示socket所处的状态,是一个枚举变量,其类型定义如下:
    typedef enum {
        SS_FREE = 0,            //该socket还未分配
        SS_UNCONNECTED,         //未连向任何socket
        SS_CONNECTING,          //正在连接过程中
        SS_CONNECTED,           //已连向一个socket
        SS_DISCONNECTING        //正在断开连接的过程中
    }socket_state;

    该成员只对TCP socket有用,因为只有tcp是面向连接的协议,udp跟raw不需要维护socket状态。
    flags是一组标志位,在内核中并没有发现被使用。
    ops是协议相关的一组操作集,结构体struct proto_ops的定义如下:
   
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);
        int (*getname)(struct socket *sock, struct sockaddr *addr,int *sockaddr_len, int peer);
        unsigned int (*poll)(struct file *file, struct socket *sock,
                        struct poll_table_struct *wait);
        int (*ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg);
        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, int optlen);
        int (*getsockopt)(struct socket *sock, int level,
                        int optname, char __user *optval, int __user *optlen);
        int (*sendmsg)(struct kiocb *iocb, struct socket *sock,
                        struct msghdr *m, size_t total_len);
        int (*recvmsg)(struct kiocb *iocb, 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);
    };
    
协议栈中总共定义了三个strcut proto_ops类型的变量,分别是myinet_stream_ops, myinet_dgram_ops, myinet_sockraw_ops,对应流协议, 数据报和原始套接口协议的操作函数集。
    type是socket的类型,对应的取值如下:
    enum sock_type {
        SOCK_DGRAM = 1,
        SOCK_STREAM = 2,
        SOCK_RAW    = 3,
        SOCK_RDM    = 4,
        SOCK_SEQPACKET = 5,
        SOCK_DCCP   = 6,
        SOCK_PACKET = 10,
    };

    sk是网络层对于socket的表示,结构体struct sock比较庞大,这里不详细列出,只介绍一些重要的成员,
    sk_prot和sk_prot_creator,这两个成员指向特定的协议处理函数集,其类型是结构体struct proto,该结构体也是跟struct proto_ops相似的一组协议操作函数集。这两者之间的概念似乎有些混淆,可以这么理解,struct proto_ops的成员操作struct socket层次上的数据,处理完了,再由它们调用成员sk->sk_prot的函数,操作struct sock层次上的数据。即它们之间存在着层次上的差异。struct proto类型的变量在协议栈中总共也有三个,分别是mytcp_prot,myudp_prot,myraw_prot,对应TCP, UDP和RAW协议。
    sk_state表示socket当前的连接状态,是一个比struct socket的state更为精细的状态,其可能的取值如下:   
     enum {
        TCP_ESTABLISHED = 1,
        TCP_SYN_SENT,
        TCP_SYN_RECV,
        TCP_FIN_WAIT1,
        TCP_FIN_WAIT2,
        TCP_TIME_WAIT,
        TCP_CLOSE,
        TCP_CLOSE_WAIT,
        TCP_LAST_ACK,
        TCP_LISTEN,
        TCP_CLOSING,

        TCP_MAX_STATES
    };

    这些取值从名字上看,似乎只使用于TCP协议,但事实上,UDP和RAW也借用了其中一些值,在一个socket创建之初,其取值都是 TCP_CLOSE,一个UDP socket connect完成后,将这个值改为TCP_ESTABLISHED,最后,关闭sockt前置回TCP_CLOSE,RAW也一样。
    sk_rcvbuf和sk_sndbuf分别表示接收和发送缓冲区的大小。sk_receive_queue和sk_write_queue分别为接收缓 冲队列和发送缓冲队列,队列里排列的是套接字缓冲区struct sk_buff,队列中的struct sk_buff的字节数总和不能超过缓冲区大小的设定。

接着上一篇,继续介绍struct sock。
    sk_rmem_alloc, sk_wmem_alloc和sk_omem_alloc分别表示接收缓冲队列,发送缓冲队列及其它缓冲队列中已经分配的字节数,用于跟踪缓冲区的使用情况。
    struct sock有一个struct sock_common成员,因为struct inet_timewait_sock也要用到它,所以把它单独归到一个结构体中,其定义如下:
    struct sock_common {
        unsigned short      skc_family;
        volatile unsigned char skc_state;
        unsigned char       skc_reuse;
        int         skc_bound_dev_if;
        struct hlist_node   skc_node;
        struct hlist_node   skc_bind_node;
        atomic_t        skc_refcnt;
        unsigned int        skc_hash;
        struct proto        *skc_prot;
    };


    struct inet_sock。
    这是INET域专用的一个socket表示,它是在struct sock的基础上进行的扩展,在基本socket的属性已具备的基础上,struct inet_sock提供了INET域专有的一些属性,比如TTL,组播列表,IP地址,端口等,下面是其完整定义:
struct inet_sock {
            struct sock     sk;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
            struct ipv6_pinfo   *pinet6;
#endif
            __u32           daddr;          //IPv4的目的地址。
            __u32           rcv_saddr;      //IPv4的本地接收地址。
            __u16           dport;          //目的端口。
            __u16           num;            //本地端口(主机字节序)。
            __u32           saddr;          //发送地址。
            __s16           uc_ttl;         //单播的ttl。
            __u16           cmsg_flags;
            struct ip_options   *opt;
            __u16           sport;          //源端口。
            __u16           id;             //单调递增的一个值,用于赋给iphdr的id域。
            __u8            tos;            //服务类型。
            __u8            mc_ttl;         //组播的ttl
            __u8            pmtudisc;
            __u8            recverr:1,
                            is_icsk:1,
                            freebind:1,
                            hdrincl:1,      //是否自己构建ip首部(用于raw协议)
                            mc_loop:1;      //组播是否发向回路。
            int             mc_index;       //组播使用的本地设备接口的索引。
            __u32           mc_addr;        //组播源地址。
            struct ip_mc_socklist   *mc_list;   //组播组列表。
            struct {
                unsigned int        flags;
                unsigned int        fragsize;
                struct ip_options   *opt;
                struct rtable       *rt;
                int                 length;
                u32                 addr;
                struct flowi        fl;
            } cork;
        };

    struct raw_sock
    这是RAW协议专用的一个socket的表示,它是在struct inet_sock基础上的扩展,因为RAW协议要处理ICMP协议的过滤设置,其定义如下:
    struct raw_sock {
        struct inet_sock   inet;
        struct icmp_filter filter;
    };


    struct udp_sock
    这是UDP协议专用的一个socket表示,它是在struct inet_sock基础上的扩展,其定义如下:
    struct udp_sock {
        struct inet_sock inet;
        int             pending;
        unsigned int    corkflag;
        __u16           encap_type;
        __u16           len;
    };


    struct inet_connection_sock
    看完上面两个,我们觉得第三个应该就是struct tcp_sock了,但事实上,struct tcp_sock并不直接从struct inet_sock上扩展,而是从struct inet_connection_sock基础上进行扩展,struct inet_connection_sock是所有面向连接的socket的表示,关于该socket,及下面所有tcp相关的socket,我们在分析 tcp实现时再详细介绍,这里只列出它们的关系。

    strcut tcp_sock
    这是TCP协议专用的一个socket表示,它是在struct inet_connection_sock基础进行扩展,主要是增加了滑动窗口协议,避免拥塞算法等一些TCP专有属性。

    struct inet_timewait_sock

    struct tcp_timewait_sock
    在struct inet_timewait_sock的基础上进行扩展。

    struct inet_request_sock

    struct tcp_request_sock
    在struct inet_request_sock的基础上进行扩展。

分享到:
评论

相关推荐

    struct sock详解

    struct sock 详解 ...struct socket是一个非常重要的数据结构,在Linux内核中扮演着至关重要的角色,它是 socket 编程的基础,理解 struct socket 的结构和成员变量对编写高效的网络应用程序非常重要。

    Socket编程详解

    ### Socket编程详解 #### 一、基本知识 在进行Socket编程之前,理解基本概念非常重要,这些概念包括主机字节序与网络字节序的区别、缓冲区的作用以及通信域的定义等。 ##### 主机字节序与网络字节序 计算机在处理...

    C++socket编程详解

    ### C++ Socket编程详解 #### 一、C++ Socket编程概览 在现代软件开发中,网络编程是一项不可或缺的技术,特别是在分布式系统、互联网应用及移动应用等领域。**Visual C++**(简称VC)作为一种强大的开发工具,...

    socket函数详解

    Socket函数详解 Socket编程是计算机网络编程的基础,它允许程序创建和使用网络连接进行通信。在本文中,我们将深入理解socket函数以及相关的数据结构,这对于初学者来说是至关重要的。 首先,我们来看`struct ...

    linux 中socket编程 常用结构体 详解

    Linux 中 Socket 编程常用结构体详解 Linux 中 Socket 编程常用结构体是指在 Linux 操作系统中,用于实现网络通信的结构体。这些结构体是 Socket 编程的基础,是理解 Socket 编程的关键。 首先,我们需要了解...

    mtcp 数据结构详解

    ### mTCP 数据结构详解 mTCP(多线程TCP)是一种高效的网络通信库,它能够支持高并发场景下的网络通信需求。为了更好地理解和利用mTCP的功能特性,本篇将深入剖析mTCP中的关键数据结构。 #### mTCP Manager 结构体...

    socket详解

    ### Socket详解 #### 一、什么是Socket? 在探讨Socket的具体工作原理之前,首先明确一点:Socket是一种用于程序间通信的标准接口。它允许不同进程通过网络进行数据交换,无论是同一主机还是不同主机之间的通信。 ...

    socket_linux-socket网络编程详解_

    在Linux Socket编程中,我们需要定义服务器和客户端的网络地址,这通常使用`struct sockaddr_in`结构体完成。包含IP地址和端口号。 ```c struct sockaddr_in server; server.sin_family = AF_INET; server.sin_addr...

    socket send和recv详解

    Socket 编程中的 send 和 recv 函数详解 在 Socket 编程中,send 和 recv 函数是最基本的网络通信函数。它们用于在客户端和服务端之间传递数据。在 TCP/IP 协议中,send 函数用于将数据发送到服务端,而 recv 函数...

    linux-socket网络编程详解.doc

    - **connect()函数**:在面向连接的Socket中,客户端使用connect()函数与服务器建立连接,并将本地和远程的地址信息存储在Socket数据结构中。 - **listen()函数**:仅适用于服务器端,设置Socket为监听模式,等待...

    Linux下Socket编程基础详解(含网络传输实例代码)

    ### Linux下Socket编程基础详解 #### 一、引言 在深入探讨Socket编程之前,我们首先需要理解什么是Socket。在计算机网络中,Socket是应用程序与网络通信之间的一个接口,它提供了一种方式来建立网络连接并进行数据...

    IPV4与IPV6兼容socket编程接口详解[归纳].pdf

    IPV4与IPV6兼容socket编程接口详解 在计算机网络通信中,套接字(Socket)是一种编程接口,允许不同进程之间进行通信。 IPV4与IPV6兼容的套接字编程接口是指同时支持IPV4和IPV6两种网络协议的套接字编程接口。 套...

    有关socket编程的函数详解

    ### 有关socket编程的函数详解 #### 一、概述 Socket编程是网络编程的重要组成部分,它使得不同计算机之间可以通过网络进行通信。在Windows环境下,使用socket编程时,我们需要调用一系列特定的API函数来实现这一...

    windows下socket通信代码

    在Windows环境下进行网络编程时,Socket通信是一种常用的技术。Socket接口是操作系统提供的网络通信API,允许应用程序通过TCP/IP协议栈与其他计算机进行数据交换。本文将详细介绍Windows下的Socket通信代码,包括...

    SocketSocket详细介绍,C++,原理

    ### Socket详解:C++与原理 #### 一、Socket是什么? 在计算机网络中,Socket(套接字)是一种实现进程间通信(IPC)的方式。它为应用层软件提供了访问低层传输协议的服务,使得不同主机上的应用程序能够进行双向...

    linux socket

    ### Linux Socket 编程详解 #### 一、引言 Socket 是一种用于网络通信的机制,使得不同计算机上的进程能够互相通信。在 Linux 操作系统中,Socket 编程是实现这一功能的主要方式之一。本篇文章将深入探讨 Linux 下 ...

    Socket模型c++版本详解

    ### Socket模型C++版本详解 #### 一、引言 Socket是网络编程中不可或缺的一部分,它使得不同计算机之间能够通过网络进行数据交换。在Windows环境下,实现Socket的主要库是Winsock,而C++作为一种强大的面向对象语言...

    追踪LINUX TCP/IP代码运行二

    通过对`struct socket`和`struct sock`这两个核心数据结构的分析,我们可以更深入地理解Linux内核中Socket的工作原理。在实际开发中,正确理解和运用这些概念将有助于编写高效、稳定的网络应用程序。此外,掌握这些...

Global site tag (gtag.js) - Google Analytics