linux 网络套接字

在内核分析网络分组时,底层协议的数据将传输到跟高的层。而发送数据的时候顺序是相反的。每一层都是通过加(首部+净荷)传向跟底层,直至最终发送。

这些操作决定了网络的的性能。

就如下图所示

linux因此设计了一个结构体

如下代码


/**
 *  struct sk_buff - socket buffer
 *  @next: Next buffer in list
 *  @prev: Previous buffer in list
 *  @list: List we are on
 *  @sk: Socket we are owned by
 *  @stamp: Time we arrived
 *  @dev: Device we arrived on/are leaving by
 *      @real_dev: The real device we are using
 *  @h: Transport layer header
 *  @nh: Network layer header
 *  @mac: Link layer header
 *  @dst: FIXME: Describe this field
 *  @cb: Control buffer. Free for use by every layer. Put private vars here
 *  @len: Length of actual data
 *  @data_len: Data length
 *  @csum: Checksum
 *  @__unused: Dead field, may be reused
 *  @cloned: Head may be cloned (check refcnt to be sure)
 *  @pkt_type: Packet class
 *  @ip_summed: Driver fed us an IP checksum
 *  @priority: Packet queueing priority
 *  @users: User count - see {datagram,tcp}.c
 *  @protocol: Packet protocol from driver
 *  @security: Security level of packet
 *  @truesize: Buffer size
 *  @head: Head of buffer
 *  @data: Data head pointer
 *  @tail: Tail pointer
 *  @end: End pointer
 *  @destructor: Destruct function
 *  @nfmark: Can be used for communication between hooks
 *  @nfcache: Cache info
 *  @nfct: Associated connection, if any
 *  @nf_debug: Netfilter debugging
 *  @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
 *      @private: Data which is private to the HIPPI implementation
 *  @tc_index: Traffic control index
 */

struct sk_buff {
    /* These two members must be first. */
    struct sk_buff      *next;
    struct sk_buff      *prev;

    struct sk_buff_head *list;
    struct sock     *sk;
    struct timeval      stamp;
    struct net_device   *dev;
    struct net_device   *real_dev;

    union {
        struct tcphdr   *th;
        struct udphdr   *uh;
        struct icmphdr  *icmph;
        struct igmphdr  *igmph;
        struct iphdr    *ipiph;
        unsigned char   *raw;
    } h;

    union {
        struct iphdr    *iph;
        struct ipv6hdr  *ipv6h;
        struct arphdr   *arph;
        unsigned char   *raw;
    } nh;

    union {
        struct ethhdr   *ethernet;
        unsigned char   *raw;
    } mac;

    struct  dst_entry   *dst;
    struct  sec_path    *sp;

    /*
     * This is the control buffer. It is free to use for every
     * layer. Please put your private variables there. If you
     * want to keep them across layers you have to do a skb_clone()
     * first. This is owned by whoever has the skb queued ATM.
     */
    char            cb[48];

    unsigned int        len,
                data_len,
                csum;
    unsigned char       local_df,
                cloned,
                pkt_type,
                ip_summed;
    __u32           priority;
    unsigned short      protocol,
                security;

    void            (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
        unsigned long       nfmark;
    __u32           nfcache;
    struct nf_ct_info   *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
        unsigned int        nf_debug;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
    struct nf_bridge_info   *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#if defined(CONFIG_HIPPI)
    union {
        __u32       ifield;
    } private;
#endif
#ifdef CONFIG_NET_SCHED
       __u32            tc_index;               /* traffic control index */
#endif

    /* These elements must be at the end, see alloc_skb() for details.  */
    unsigned int        truesize;
    atomic_t        users;
    unsigned char       *head,
                *data,
                *tail,
                *end;
};

套接字换从区在各个层交换数据,就不用复制数据了。

从以上字段和注释可以看到,head和end字段指向了buf的起始位置和终止位置。然后使用header指针指像各种协议填值。然后data就是实际数据。tail记录了数据的偏移值。

相信大家都能看懂注释,具体的解释就不用介绍了.,

在一个新的分组产生的时候,TCP层首先在用户空间中分配内存来容纳该分组数据。分配的空间大于数据的实际需要长度。因此较低的层可以增加首部,在往下一层走的时候,只需要对字段添值即可。

对接收分组的一样,分组数据复制到内核分配的一个内存区中。并在分析的过程中一直处于内存区中。

skbuf还提供了一个双向链表对这个数据分组进行了管理。

如下代码

struct sk_buff_head {
    /* These two members must be first. */
    struct sk_buff  *next;
    struct sk_buff  *prev;

    __u32       qlen;
    spinlock_t  lock;
};

__u32 qlen; 缓冲区中等待队列的长度。就是分组的成员数量。

lock 表示了cpu的互斥。

今天分析到此,跟多源码阅读去看skbuff.h的文件。

原文地址:https://www.cnblogs.com/linhaostudy/p/10352860.html

时间: 2024-08-06 10:25:51

linux 网络套接字的相关文章

APUE中网络套接字一章——使用pthread改写远程时间服务器

最近在看<Unix环境高级编程>一书,我一直对网络编程有兴趣,所以就直接跳到了网络套接字这一章. 这一章中有一个示例程序:一个TCP客户端向服务器发送连接请求,服务器在接受请求后,调用uptime命令 并将结果返回给客户端,客户端再将其打印出来. 因为前面刚看过线程那一章,所以我想把服务器改造成多线程的,以便同时服务多个线程.但是却碰到 一个问题,调试了半天还是没有进展(linux下调试我真的不是很会),google了下也没找到答案.索性先po 上来,整理下思路,如果有园子里的朋友能够帮忙解答

Linux编程---套接字

网络相关的东西几乎都是建立在套接字之上.所以这个内容对于程序员来说还是蛮重要的啊. 其实套接字也就是一个特殊的设备文件而已,我始终不能明白为什么要叫套接字.这么个奇怪的名字.不过还是就这样算了吧.关键还是编程上.由于其重要性,我还是写的详细一点吧. 一.套接字 核心函数: int  socket(int domain,int type,int protocol); 这个函数在通信域domain中创建一个类型为type,使用协议protocol的套接字.并且返回一个描述字,也就是相当于打开了一个特

Linux/UNIX套接字连接

套接字连接 套接字是一种通信机子.凭借这样的机制.客户/server系统的开发工作既能够在本地单机上进行.也能够夸网络进行. 套接字的创建和使用与管道是有差别的.由于套接字明白地将客户和server区分开来. 套接字连接: 首先,server应用程序用系统调用socket来创建一个套接字,它是系统分配给该server进程的类似文件描写叙述符的资源,它不能与其它进程共享. 接下来.server进程会给套接字起个名字.本地套接字的名字是Linux文件系统中的文件名称,对于网络套接字它的名字是与客户连

linux 的套接字

套接字是一种通信机制,凭借这种机制,客户/服务器系统的开发工作既可以在本地单机上进行,也可以跨网络进行. 套接字的特性有三个属性确定,它们是:域(domain),类型(type),和协议(protocol).套接字还用地址作为它的名字.地址的格式随域(又被称为协议族,protocol family)的不同而不同.每个协议族又可以使用一个或多个地址族定义地址格式. 1.套接字的域 域指定套接字通信中使用的网络介质.最常见的套接字域是AF_INET,它是指Internet网络,许多Linux局域网使

Linux 原始套接字--myping的实现

一.套接字的类型 A.流套接字(SOCK_STREAM) 用于提供面向连接.可靠的数据传输服务,其使用传输层的TCP协议 B.数据报套接字(SOCK_DGRAM) 用于提供一个无连接.不可靠的服务,其使用传输层上的UDP协议 C.原始套接字(SOCK_RAM) 原始套接字是相对表中套接字(即前面两种套接字)而言的.它与标准套接字的区别是原始套接字可以读写内核没有处理的IP数据包,流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据. 所以要访问其他协议的数据必须使用原始套接字.

什么是网络套接字(Socket)?

什么是网络套接字(Socket)?一时还真不好回答,而且网络上也有各种解释,莫衷一是.下文将以本人所查阅到的资料来说明一下什么是Socket. 1. Socket定义 Socket在维基百科的定义: A network socket is an endpoint of an inter-process communication across a computer network. Today, most communication between computers is based on t

linux netlink套接字学习资料

理论: http://blog.csdn.net/unbutun/article/details/3394061 进一步深入: http://edsionte.com/techblog/archives/4134 http://edsionte.com/techblog/archives/4140 http://edsionte.com/techblog/archives/4134 实践: http://bbs.chinaunix.net/thread-3766684-1-1.html 附录代码

linux netlink套接字实现类似ss命令 ,统计套接字以及TCP信息

参考了 ss的源代码 以及 netlink相关资料:http://blog.csdn.net/scdxmoe/article/details/27711205 实现结果为: gcc netlink_dig_530_7.c -o netlink_dig_530_7 ./netlink_dig_530_7 state      family     l.addr     l.port       r.addr     r.rport LISTEN     AF_INET   localhost  

Linux - Socket网络套接字

OSI七层协议功能 物理层 面向物理传输媒体,屏蔽媒体的不同 主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的地后在转化为1.0,也就是我们常说的模数转换与数模转换).这一层的数据叫做比特. 链路层 面向一条链路,成帧和无差错传输 主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装.常把这一层的数据叫做帧.在这一层工作的设备是交换机,数据通过交换机来传输. 网络层 分配地址.