Socket套接字
现有计算机网络体系结构有三种划分形式:OSI七层协议、TCP/IP四层协议结构、五层协议结构。具体介绍参考:【嵌入式开发之网络编程】网络分层、OSI七层模型、TCP/IP及五层体系结构
网络的体系结构 (Network Architecture) 是计算机网络的各层及其协议的集合,就是这个计算机网络及其构件所应完成的功能的精确定义(不涉及实现)。
实现 (implementation) 是遵循这种体系结构的前提下,用何种硬件或软件完成这些功能的问题。
几种常见的网络编程接口
- Berkeley UNIX 操作系统定义了一种 API,它又称为套接字接口 (socket interface)
- 微软公司在其操作系统中采用了套接字接口 API,形成了一个稍有不同的 API,并称之为 Windows Socket
- AT&T 为其 UNIX 系统 V 定义了一种 API,简写为 TLI (Transport Layer Interface)
套接字的基本概念
套接字(Socket)就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口。
套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。
套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。 Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制。
Socket是面向客户/服务器模型而设计的。通信的一方扮演客户机的角色,另一方扮演服务器的角色。服务器在运行中一直监听套接字指定的传输层端口,并等待着客户机的连接请求。当服务器端收到客户机发来的连接请求以后,服务器会接受客户机的连接请求,双方建立连接后,就可进行数据的传递。
套接字的类型
Socket处于网络协议的传输层套接字可以分为流套接字、数据报套接字和原始套接字3种不同的类型。
- 流式套接字 (SOCK_STREAM) 提供可靠的、面向连接的通信流;它使用TCP,从而保证数据传输的可靠性和顺序性。
- 数据报套接字 (SOCK_DGRAM) 定义了一种不可靠、面向无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP。
- 原始套接字(SOCK_RAW) 允许直接访问底层协议,如IP或ICMP,它功能强大但使用较为不便,主要用于协议开发。
套接字是一种特殊的文件描述符,UNIX域套接字用于进程间通信。
套接字是服务器和客户端各自维护一个“文件”,在建立连接后,向自己文件写入内容供对方读取或者读取对方内容,通信结束时关闭文件。
套接字的地址族
socket通用地址族结构体
socket 网络编程接口中表示 socket 地址的是结构体 sockaddr,其定义如下:
#include <bits/socket.h>
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
typedef unsigned short int sa_family_t;
sa_family 成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议 族(protocol family,也称domain)和对应的地址族入下所示:
协议族 | 地址族 | 描述 |
PF_UNIX | AF_UNIX | UNIX本地域协议族 |
PF_INET | AF_INET | TCP/IPv4协议族 |
PF_INET6 | AF_INET6 | TCP/IPv6协议族 |
宏 PF_* 和 AF_* 都定义在 bits/socket.h 头文件中,且后者与前者有完全相同的值,所以二者通常混用。
sa_data 成员用于存放 socket 地址值。但是,不同的协议族的地址值具有不同的含义和长度,如下所示:
协议族 | 地址值含义和长度 |
PF_UNIX | 文件的路径名,长度可达108字节 |
PF_INET | 16 bit端口号和32 bit IPv4地址,共6个字节 |
PF_INET6 | 16 bit端口号、32 bit 流标识和 128 bit IPv6地址,共6个字节,32 bit范围ID,共26字节 |
由此可知,14 字节的sa_data 根本无法容纳多数协议族的地址值。
因此,Linux定义了下面这个新的通用的 socket 地址结构体,这个结构体不仅提供了足够大的空间用于存放地址值,而且是内存对齐的。
#include <bits/socket.h>
struct sockaddr_storage
{
sa_family_t sa_family;
unsigned long int __ss_align;