Linux网络编程-1-socket概念与地址api

socket概念

套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口 。

也可以参考wiki中的描述:

A network socket is a software structure within a network node of a computer network that serves as an endpoint for sending and receiving data across the network. The structure and properties of a socket are defined by an application programming interface (API) for the networking architecture. Sockets are created only during the lifetime of a process of an application running in the node.

Because of the standardization of the TCP/IP protocols in the development of the Internet, the term network socket is most commonly used in the context of the Internet protocol suite, and is therefore often also referred to as Internet socket. In this context, a socket is externally identified to other hosts by its socket address, which is the triad of transport protocol, IP address, and port number.

The term socket is also used for the software endpoint of node-internal inter-process communication (IPC), which often uses the same API as a network socket.

socket的历史

socket 是加州大学伯克利分校的研究人员在 20 世纪 80 年代早期提出的,所以也被叫做伯 克利套接字。伯克利的研究者们设想用 socket 的概念,屏蔽掉底层协议栈的差别。第一版 实现 socket 的就是 TCP/IP 协议,最早是在 BSD 4.2 Unix 内核上实现了 socket。很快大 家就发现这么一个概念带来了网络编程的便利,于是有更多人也接触到了 socket 的概念。 Linux 作为 Unix 系统的一个开源实现,很早就从头开发实现了 TCP/IP 协议,伴随着 socket 的成功,Windows 也引入了 socket 的概念。于是在今天的世界里,socket 成为 网络互联互通的标准。

套接字地址格式

通用套接字地址

/* POSIX.1g 规范规定了地址族为 2 字节的值.  */
typedef unsigned short int sa_family_t;
/* 描述通用套接字地址  */
struct sockaddr{
    sa_family_t sa_family;  /* 地址族.  16-bit*/
    char sa_data[14];   /* 具体的地址值 112-bit */
  }; 	

地址族表示使用什么样的方式对地址进行解释和保存。地址族在 glibc 里的定义非常多,常用的有以下几种:

  • AF_LOCAL:表示的是本地地址,对应的是 Unix 套接字,这种情况一般用于本地 socket 通信,很多情况下也可以写成 AF_UNIX、AF_FILE;
  • AF_INET:因特网使用的 IPv4 地址;
  • AF_INET6:因特网使用的 IPv6 地址。

其中 AF_ 是 Address Family, PF_ 的意思是 Protocol Family,是协议族的意思。一般用 AF_xxx 这样的值来初始化 socket 地址,用 PF_xxx 这样的值来初始化 socket。在 <sys/socket.h> 头文件中可以清晰地看到,这两个值本身就是一一对应的。

/* 各种地址族的宏定义  */
#define AF_UNSPEC PF_UNSPEC
#define AF_LOCAL  PF_LOCAL
#define AF_UNIX   PF_UNIX
#define AF_FILE   PF_FILE
#define AF_INET   PF_INET
#define AF_AX25   PF_AX25
#define AF_IPX    PF_IPX
#define AF_APPLETALK  PF_APPLETALK
#define AF_NETROM PF_NETROM
#define AF_BRIDGE PF_BRIDGE
#define AF_ATMPVC PF_ATMPVC
#define AF_X25    PF_X25
#define AF_INET6  PF_INET6

IPV4 套接字地址

IPv4 地址族的结构如下:

/* IPV4 套接字地址,32bit 值.  */
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };
  
/* 描述 IPV4 的套接字地址格式  */
struct sockaddr_in
  {
    sa_family_t sin_family; /* 16-bit */
    in_port_t sin_port;     /* 端口口  16-bit*/
    struct in_addr sin_addr;    /* Internet address. 32-bit */
 
 
    /* 这里仅仅用作占位符,不做实际用处  */
    unsigned char sin_zero[8];
  };

sin_family 字段,对于 IPv4 来说就是 AF_INET。

端口号sin_port字段,是 16-bit(2^16 = 65536),因此支持寻址的端口号最多就是 65535。所谓保留端口就是大家约定俗成的,已经被对应服务广为使用的端口,比如 ftp 的 21 端口,ssh 的 22 端口,http 的 80 端口等。一般而言,大于 5000 的端口可以作为我们自己应用程序的端口使用。

地址sin_addr字段,为一个32-bit整数,因此最多支持2^ 32(约42亿)的地址数目。

IPV6 套接字地址

ipv6地址结果如下:

struct sockaddr_in6
  {
    sa_family_t sin6_family; /* 16-bit */
    in_port_t sin6_port;  /* 传输端口号 # 16-bit */
    uint32_t sin6_flowinfo; /* IPv6 流控信息 32-bit*/
    struct in6_addr sin6_addr;  /* IPv6 地址 128-bit */
    uint32_t sin6_scope_id; /* IPv6 域 ID 32-bit */
  };

地址族位 AF_INET6,端口同 IPv4 地址一样。

地址从 32 位升级到 128 位,解决了寻址数字不够的问题。

本地套接字地址

本地套接字格式一般用来做为本地进程间的通信, 地址族为AF_LOCAL。

struct sockaddr_un {
    unsigned short sun_family; /* 固定为 AF_LOCAL */
    char sun_path[108];   /* 路径名 */
};

Linux网络编程-1-socket概念与地址api

reference

[1] 百度百科

[2] wiki

[3] 极客时间·网络编程实战

[4] Linux高性能服务器编程

上一篇:iOS开发——轻松学习Socket


下一篇:3D Vision 十讲:第七讲