套接字编程(sys / socket.h)

时间:2015-09-23 15:19:36

标签: c sockets websocket ip webserver

查看定义的sys/socket.h规范的通用套接字结构,它列出了:

sa_family_t   sa_family       address family
char          sa_data[]       socket address (variable-length data)

查看我的linux机器上位于/usr/includes/sys/socket.h的实际头文件,它定义如下。

 struct osockaddr
      {
        unsigned short int sa_family;
        unsigned char sa_data[14];
      };

现在我知道如果我添加netinet/in.h它会定义sockaddr_in结构,因为我使用AF_INET它会使用它...

struct sockaddr_in {
   short int            sin_family;
   unsigned short int   sin_port;
   struct in_addr       sin_addr;
   unsigned char        sin_zero[8];
};

但是,当我可以简单地使用通用osockaddr结构时,我认为没有必要#include另一个lib(netinet / in.h)。

现在我了解我的osockaddr成员sa_family将与AF_INET有关但我不清楚sa_data成员内部究竟发生了什么...我假设{ {1}}与port,addr,zero结构相关,但我不清楚。

问题:有人能举例说明使用通用sockaddr_in结构的示例吗?

到目前为止我所拥有的......

osockaddr

2 个答案:

答案 0 :(得分:0)

不要这样做。
你可以把sockaddr想象成一种联盟:

struct sockaddr
{
  short int sin_family;
  union {
    struct {
      unsigned short int   sin_port;
      struct in_addr       sin_addr;
      unsigned char        sin_zero[8];
    };
    unsigned char sa_data[14]
  };
};

所以,是的,如果你把sin_port的两个字节用来表示正确的字节序,你可以将它们放在sa_data[0]sa_data[1]中,然后你可以sin_addr将4个字节放入sa_data[2]sa_data[6] 但是你真的不应该这样做,因为编程非常糟糕,它会使你的代码对其他任何人都不可读,包括6个月内你自己。 如果由于某些奇怪的原因你不想#include "netinet/in.h",你可以在你自己的代码文件中定义这个结构并使用它。

答案 1 :(得分:0)

netinet/in.h不是额外的库,它只是您要以任何方式链接的一个库的定义子集。

这个通用地址就像一个抽象基类。你不应该创造它。如果您不关心您拥有的地址类型或是否要接受任何类型的地址,则只能使用它。

用法看起来像这样。

/* print any kind of socket address */
void prettyPrintAddress(struct sockaddr *addr) {
  switch (addr->sa_family) {
     case AF_INET:
       // Typocast to the actual type
       struct sockaddr_in *in_addr = (struct sockaddr_in *)addr;
       // print [ipv4]:protocl:ipv4:port
       break;
     case AF_INET6:
       // Typocast to the actual type
       struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)addr;
       // print [ipv6]:protocl:ipv6:port
       break;
     case AF_UNIX:
       // Typocast to the actual type
       struct sockaddr_un *un_addr = (struct sockaddr_un *)addr;
       // print [unix]:socket-path
       break;
     ...
  }
}

prettyPrintAddress(anyAddress);
prettyPrintAddress((struct sockaddr *) in_addr);
prettyPrintAddress((struct sockaddr *) in6_addr);
prettyPrintAddress((struct sockaddr *) un_addr);