精华内容
下载资源
问答
  • 套接字地址结构

    千次阅读 2017-03-25 16:14:02
    简介大多数套接字函数都需要一个指向套接字地址结构的指针...IPv4套接字地址结构IPv4套接字地址结构通常也称为“网际套接字地址结构”,它以sockaddr_in命名,定义在头文件中。它的定义如下:struct in_addr { in_

    简介

    大多数套接字函数都需要一个指向套接字地址结构的指针作为参数。每个协议族都定义它自己的套接字地址结构。这些结构的名字均以“sockaddr_”开头,并以对应每个协议族的唯一后缀结尾。

    IPv4套接字地址结构

    IPv4套接字地址结构通常也称为“网际套接字地址结构”,它以sockaddr_in命名,定义在<netinet/in.h>头文件中。它的定义如下:

    struct in_addr
     {
        in_addr_t s_addr;    /*  32-bit IPv4 Internet address.  */
     };
    struct sockaddr_in
      {
        __SOCKADDR_COMMON (sin_);
        in_port_t sin_port;         /* 16-bit TCP or UDP Port number.  */
        struct in_addr sin_addr;        /*  32-bit IPv4 Internet address.  */
    
        /* Pad to size of `struct sockaddr'.  */
        unsigned char sin_zero[sizeof (struct sockaddr) -
                   __SOCKADDR_COMMON_SIZE -
                   sizeof (in_port_t) -
                   sizeof (struct in_addr)];
      };

    其中宏“__SOCKADDR_COMMON()”的内容如下:

    #define __SOCKADDR_COMMON(sa_prefix) \
    sa_family_t sa_prefix##family

    它会使用参数作为family的前缀,比如上面的 _SOCKADDR_COMMON (sin),对应“sa_family_t sin_family”。

    说明

    • sin_zero字段未曾使用,不过在填写这种套接字地址结构时,我们总是把该字段置为0,按照惯例,我 们总是在填写前把整个结构置为0,而不单是把sin_zero字段置为0。

    • 套接字地址结构仅在给定主机上使用,虽然结构中的某些字段(例如IP地址和端口号)用在不同主机之间的通信中,但是结构本身并不在主机之间传递。

    • 在上面的套接字地址结构中,in_addr_t数据类型必须是一个至少32位的无符号整数类型,in_port_t必须是一个至少16位的无符号整数类型,而sa_family_t可以是任何无符号整数类型。在支持长度字段(sin_zero)的实现中,sa_family_t通常是一个8位的无符号整数,而在不支持长度的实现中,它则是一个16位的无符号整数。下图列出了POSIX定义的这些数据类型。
    数据类型说明头文件
    int8_t带符号的8位整数sys/types.h
    uint8_t无符号的8位整数<sys/types.h>
    int16_t带符号的16位整数<sys/types.h>
    uint16_t无符号的16位整数<sys/types.h>
    int32_t带符号的32位整数<sys/types.h>
    uint32_t无符号的32位整数<sys/types.h>
    sa_family_t套接字地址结构的地址族<sys/socket.h>
    socklen_t套接字地址结构的长度,一般为uint32_5<sys/socket.h>
    in_addr_tIPv4地址,一般为uint32_t<netinet/in.h>
    in_port_tTCP或UDP端口,一般为uint16_t<netinet/in.h>

    通用套接字地址结构

    前面提到过,不同主机的套接字地址结构只在本机上使用,而在不同主机之间传递的至少其中的某些字段。然而套接字函数必须处理来所有支持的任何协议族的套接字地址结构。为了解决这个问题,第一种方法是使用ANSI C中的void *指针类型,因为它是通用指针类型。然而套接字函数是在其之前定义的。所以在当时所采用的办法是在<sys/socket.h>定义一个通用的套接字地址结构(不同的操作系统写法可能不一样,但是本质内容是相同的),如下:

    struct sockaddr {
        uint8_t    sa_len;    
        sa_family_t    sa_family;    /* address family: AF_xxx value */
        char    sa_data[14];    /* protocol-specific address */
    };

    于是套接字函数被定义位以指向某个通用套接字地址结构的一个指针作为其参数之一,这正如同bind函数的ANSI C函数原型所示:

    int bind(int, struct sockaddr *, socklen_t);

    IPv6套接字地址结构

    IPv6套接字地址结构在<netinet/in.h>头文件中定义,如下:

    struct in6_addr
     {
         uint8_t s6_addr[16];
     };
    #define SIN6_LEN    /* required for compile-time tests */
    struct sockaddr_in6
      {
        uint8_t sin6_len  /* length of this struct (28) */
                          /* ubuntu没有这个字段 */
        __SOCKADDR_COMMON (sin6_);  /* AF_INET6 */
        in_port_t sin6_port;    /* Transport layer port # */
        uint32_t sin6_flowinfo; /* IPv6 flow information */
        struct in6_addr sin6_addr;  /* IPv6 address */
        uint32_t sin6_scope_id; /* IPv6 scope-id */
      };

    注意

    • 如果系统支持套接字地址结构中的长度字段,那么SIN6_LEN必须定义。
    • IPv6的地址族是AF_INET6, 而IPv4的地址族是AF_INET。
    • 结构中字段的先后顺序做过编排,使得如果sockaddr_in6结构本身是64位对齐(结构大小是64位的整数倍)的,那么128位的sin6_addr字段也是64位对齐的。这么做的目的是,在一些64位机器上,如果64位数据存储在某个64位边界位置(对齐),那么对它的访问会得到优化处理。
    • sin6_flowinfo字段分为两个字段: 低序20位是流标(flow label);高序12位保留。
    • 对于具备范围的地址(scoped address),sin6_scop_id字段标识其范围(scope)。

    新的通用套接字地址结构

    作为IPv6套接字API的一部分而定义的新的通用套接字地址克服了现有struct sockaddr的一些缺点。不像struct sockaddr,新的struct sockaddr_storage足以容纳系统所支持的任何套接字地址结构。它的定义如下:

    struct sockaddr_storage {
        uint8_t ss_len;    /* length of the struct (implementation dependent) */
        sa_family_t ss_family;    /* address family: AF_xxx value */
        /* implementation-dependent elements to provide:
         * a) alignment sufficient to fulfill the alignment requirement of
         *    all socket address types that the system supports.
         * b) enough storage to hold any type of socket address that the 
         *    system supports.
         * /
    };

    sockaddr_storage和sockaddr的两点差别:

    1. 如果系统支持的任何套接字地址结构有对齐需要,那么sockaddr_storage能够满足最苛刻的对齐要求。
    2. sockaddr_storage足够大,能够容纳系统支持的任何套接字地址结构。
      注意
      除了ss_family和ss_len外(如果有的话),sockaddr_storage结构中的其它字段对用户是透明的。sockaddr_storage结构必须强制类型转换成或复制到适合与ss_family字段所给出地址类型的套接字地址结构中,才能访问其他字段。
    展开全文
  • 76-抽象 unix 域套接字地址

    千次阅读 2017-05-04 19:46:35
    1. 普通 VS 抽象前面我们已经学习过了 sockaddr_un 结构,...这种 unix 域套接字地址我们称为普通 unix 域套接字地址。还有一种 unix 域套接字地址,它的特征是 sun_path[0] 是 null,即 sun_path[0] == '\0'. 这种 uni

    1. 普通 VS 抽象

    前面我们已经学习过了 sockaddr_un 结构,它有一个成员 sun_path,通常它保存的是一个以'\0'为结尾的绝对路径。一旦绑定了一个绝对路径,就会生成一个文件。这种 unix 域套接字地址我们称为普通 unix 域套接字地址

    还有一种 unix 域套接字地址,它的特征是 sun_path[0] 是 null,即 sun_path[0] == '\0'. 这种 unix 域套接字地址称为抽象 unix 域套接字地址

    2. 抽象 unix 域套接字地址

    使用这种套接字地址,它并不会在文件系统中产生真正的套接字文件,而是由内核帮我们维护一个抽象套接字文件,它总是以 '@'开头,比如 @dog。所以,它的好处自然很明显,不用产生实际文件了。

    既然 sun_path[0] == '\0',使用普通的方法就没办法得知抽象套接字文件的名字。unix 域协议规定使用套接字地址的长度来确定 sun_path.

    比如套接字地址内容如下:

    struct sockaddr_un addr = {
      AF_LOCAL, // 长度为 2
      {'\0', 'd', 'o', 'g'} // 长度为 4
    }

    则该 addr 的长度应该设置为 2 + 4 = 6.

    在 bind 抽象 unix 域套接字地址的时候,不能再使用 sizeof(addr) 作为 bind 的最后一个参数了,而应该使用上面计算出来的 6 这个结果。

    3. unix 域套接字长度计算

    在 sys/un.h 有一个宏 SUN_LEN 可以计算该 addr 的长度:

    #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))


    这里写图片描述
    图1 sys/un.h 中的源码

    不过我们不能直接在抽象的 unix 域套接字地址上使用它,因为这个宏使用到了 strlen 函数。使用的时候可以用下面的方法:

    struct sockaddr_un addr;
    addr.sun_family = AF_LOCAL;
    strcpy(addr.sun_path + 1, "dog");
    addr.sun_path[0] = '@'; // 先用非空字符占个位
    len = SUN_LEN(&addr); // 计算长度
    addr.sun_path[0] = 0; // 设置成抽象 unix 域套接字地址

    4. 实验

    程序路径:

    git clone https://git.oschina.net/ivan_allen/unp.git

    如果你已经 clone 过这个代码了,请使用 git pull 更新一下。本节程序所使用的程序路径是 unp/program/unixdomainprotocols/echo_stream.

    4.1 实验步骤

    • 启动服务器
    $ ./echo -s --path dog --abstract
    • 启动客户端
    $ ./echo --path dog --abstract

    4.2 实验结果及分析


    这里写图片描述
    图2 左侧是服务器,右侧是客户端


    这里写图片描述
    图3 netstat 输出

    从图 3 中可以看到,Path 一栏显示的路径是 @dog,而不是 dog. 图 1 中显示的运行结果也很正常。

    5. 总结

    • 普通 unix 域套接字地址和抽象 unix 域套接字地址
    • 如何创建抽象 unix 域套接字地址
    展开全文
  • 通用套接字地址结构

    千次阅读 2017-03-29 19:55:09
    当作为一个参数传递进任何套接字函数时候,套接字地址结构总是以引用的形式来传递,并且,这样有一个参数的人核桃皆自函数必须处理例子所有支持的任何协议族的套接字地址结构。因此在头文件中定义了一个通用的套接...

    1.通用套接字地址结构起因:
    当作为一个参数传递进任何套接字函数时候,套接字地址结构总是以引用的形式来传递,并且,这样有一个参数的人核桃皆自函数必须处理例子所有支持的任何协议族的套接字地址结构。因此在头文件中定义了一个通用的套接字地址结构。
    2.通用套接字地址结构

    #include <sys/socket.h>
    struct sockaddr{
        uint8_t     sa_len;
        sa_family_t sa_family;
        char        sa_data[14];
    }

    3.根据bind函数看:

    int bind(int,struct sockaddr *,socklen_t);

    对这个函数的任何调用都要求将指定特定于协议的套接字地址结构的指针进行强制类性转换,变成指向某个通用套接字地址结构的指针,如果不强制类型转换,编译出错。

    展开全文
  • 套接字地址结构看着貌似很复杂,因为经常看到定义一个地址的时候用到struct sockaddr_in,而在bind中的地址参数是struct sockaddr。他们之间的关系是什么呢?

    套接字的地址结构看着貌似很复杂,因为经常看到定义一个地址的时候用到struct sockaddr_in,而在bind中的地址参数是struct sockaddr。他们之间的关系是什么呢?

    int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
      <Unix网络编程>查阅后得出以下几条结论:
      1.不同协议簇的套接字地址的定义是不同的,如AF_INET的地址为struct socketaddr_in,而域套接字协议簇AF_UNIX的地址为struct socketaddr_un。不同地址结构定义是不同的,占用的内存大小自然不同;

      2.Struct sockaddr 是通用的地址结构,他主要负责为不同地址格式的地址能够传入到套接字函数中,即,不同协议簇的地址指针传入套接字函数的时候,指针类型将被强制转化为通用套接字地址的指针类型。

    总而言之,Struct sockaddr 是为具体的协议簇地址在套接字函数参数传递时候使用的~

    附录:

    通用套接字定义:
    typedef unsigned short sa_family_t;
    struct sockaddr {
    	sa_family_t     sa_family;    /* address family, AF_xxx */
    	char            sa_data[14];    * 14 bytes of protocol address */
    }
    
    AF_INET套接字地址格式:
    struct sockaddr_in { 
    	short int sin_family; /* 地址族 */ 
    	unsigned short int sin_port; /* 端口号 */ 
    	struct in_addr sin_addr; /* IP地址 */ 
    	unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */ 
    }; 
    
    AF_UNIX套接字地址格式:
    #define UNIX_PATH_MAX 108
    struct sockaddr_un {
    	sa_family_t sun_family; /*PF_UNIX或AF_UNIX */
    	char sun_path[UNIX_PATH_MAX]; /* 路径名 */
    };

    各个套接字地址结构的比较如下(unix网络编程:卷1):




    展开全文
  • 套接字和套接字地址结构定义

    千次阅读 2010-03-01 10:16:00
    套接字和套接字地址结构定义这段主程序是一段典型的服务器程序。网络通讯最重要的就是套接字的使用,在程序的一开始就对套接字描述符sockfd和newsockfd进行了定义。接下来定义客户机/服务器的套接字地址结构cliaddr...
  • IPv4套接字地址结构

    千次阅读 2015-11-15 15:47:02
    之前虽然写过windows socket程序,但是对套接字地址结构一直比较模糊,用的时候基本上是照着例子往上套。今天看了《UNIX网络编程》第三章,也算对套接字地址结构有了一个较为清晰的认识。 IPv4套接字地址结构以...
  • IPv4 和 IPv6 的套接字地址结构

    千次阅读 2017-08-01 21:03:57
    大多数套接字函数都需要一个指向套接字地址结构的指针作为参数,每个协议族都定义有它自己的套接字地址结构。这些结构的名字均以“sockaddr_”开头,并以对应每个协议准的唯一后缀结尾。 IPv4 套接字地址结构通常...
  • 在套接字编程中, 一个网络连接的两端是通过套接字标识的, ...比如 IPv4 的套接字地址结构: struct sockaddr_in{ uint8_t sin_len; // length of structure sa_family_t sin_family; // AF_INET in_po...
  • /**IPV4套接字地址结构**/ struct in_addr { in_addr s_addr;//32位IPV4地址,这是无符号整数,网络字节序 }; /*POSIX只关注sin_family,sin_port,sin_addr,所有网络套接字地质结构都至少16字节*/ struct...
  • 引言:套接字地址结构在网络编程的每个实现中都要用到,因此掌握套接字地址结构是以后编写网络程序的前提,地址结构可以在两个方向上传递:从进程到内核和从内核到进程。地址转换函数在地址的文本表达和他们存放在...
  • 1.套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数。每个协议族都定义它自己的套接字地址结构。这些结构的名字均以sockaddr_开头,并以对应每个协议族的唯一后缀结尾。 1.1 IPv4套接字...
  • java.net.ConnectException: Connection refused: connect;cannot bind to 127.0.0.1:5037: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (10048) 安卓端口被占用最新的解决办法127.0.0.
  • 套接字&套接字地址结构和bind()函数

    千次阅读 2015-08-03 22:35:38
    我们都知道在网络编程中,可以调用socket()函数来获取一个套接字描述符。但是,socket()函数的作用只是返回一个很小的非负整数值吗?并非如此,socket()函数的作用是创建套接字的。 创建套接字的流程如下 ...
  • 练习廖雪峰教程时,碰到这个报错:通常每个套接字地址(协议/网络地址/端口)只允许使用一次 也就是请求本地的网络端口,第一次正常显示,第二次就出错了。 原因:第一次程序运行之后,还一直在终端运行,一直占用着...
  • 每个套接字地址error

    万次阅读 2018-10-17 18:49:02
    套接字问题 1 netstat -aon|findstr 5037   2 根据pid,查询占用端口的应用,这里的pid为 8672,查询命令如图 3 杀死对应的PID,taskkill /pid 8672 /f   4 是不是杀不掉,哈哈哈哈 5 根据步骤2,在...
  • 今天在运行项目时产生了 “通常每个套接字地址(协议/网络地址/端口)只允许使用一次”这个错误。 每个网站在运行时都会分配一个端口号 如果端口号已经被其他程序占用就会出现这个错误。 我们需要修改项目的...
  • 解决androidstudio通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (10048)的错误Android模拟器端口被占用问题的解决办法 刚刚在用手机调试的时候遇到了cannot bind to 127.0.0.1:5037: 通常每个套接字...
  • 我们在做socket的开发的时候,经常会遇到这个错误:通常每个套接字地址 (协议/网络地址/端口)只允许使用一次错误指示很明确:通信端口被占用了,导致通信无法进行。但为什么端口被占用了呢?什么端口被占用了?这里...
  • Listen failure: Couldn't listen on 127.0.0.1:8000: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。. 后台 Ctrl+Alt+Esc 快捷键查看 solution for this problem: 每次修改代码后,...
  • 发现问题:在启动某程序时,提示:”通常每个套接字地址(协议/网络地址/端口)只允许使用一次". 分析:错误指示:通信端口被占用了,导致通信无法进行。 有可能是已经启动了一个程序,还有一种可能是端口被别人...
  • 用telnet测试万网提供的服务器80/21端口正常,但运行时提示“每个套接字地址只允许使用一次”错误。若把端口换为4567就能正常运行,但此端口没有开放。部分源代码如下 ```//服务器启动侦听 IPEndPoint localep = ...
  • (OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 : AH00072: make_sock: could not bind to address [::]:443 AH00451: no listening sockets available, shutting down AH00015: Unable to ...
  • UDP异常:“System.Net.Sockets.SocketException:“通常每个套接字地址(协议/网络地址/端口)只允许使用一次
  • error: could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 (10048) ... 报这个错的原因是5037端口被占用,adb已经被别的程序...
  • Android Studio 关于“error: could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037: 通常每个套接字地址只允许使用一次”的解决办法。
  • 在windows上安装Apache后无法启动,报错如下:通常每个套接字地址(协议/网络地址/端口)只允许使用一次: make_sock:could not bind to address 0.0.0.0:80,经检查是由于大意导致了IIS和Apache都使用了80端口,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 292,364
精华内容 116,945
关键字:

套接字地址