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的字節數總和不能超過緩衝區大小的設定。安全

相關文章
相關標籤/搜索