一下内容引述直《Linux/Unix系统编程手册》
Internet Domain Socket
Internet Domain流socket是基于TCP之上的,他们提供了可靠的双向字节流通信信道。
Internet domain数据报socket是基于UDP之上的。UDP socket与之在UNIX domain中的对应实体类似,但是需要注意以下差别:
- UNIX domain数据报socket是可靠的,但UDP socket则是不可靠的——数据报可能会丢失、重复或到达的顺序与他们被发送的顺序不同;
- 在一个UNIX domain数据报socket上发送数据会在接收socket的数据队列为满时阻塞。使用UDP时如果进入的数据报会使接收者的队列溢出,那么数据报就会静默被丢弃
网络字节序
IP地址和端口号是整数值。在将这些值在网络中传递时碰到的一个问题是不同的硬件结构会以不同的顺序来存储一个多字节整数的字节。
存储整数时先存储最高有效位的被称为大端,那些先存储最低有效位的被称为小端。
- 大端字节序(Big Endian):最高有效位存于最低内存地址处,最低有效位存于最高内存处;
- 小端字节序(Little Endian):最高有效位存于最高内存地址,最低有效位存于最低内存处。
在特定主机上使用的字节序被称为主机字节序
由于端口号和IP地址必须在网络中的所有主机之间传递并且需要被他们所理解,因此必须要使用一个标准的字节序。这种字节序被称为网络字节序,它是大端的。
有时候可能需要将IP地址和端口号的整数常量形式,作为一个命令行参数传递给程序
#include <arpa/inet.h>
// returns host_uint16 convered to network byte order.
uint16_t htons(uint16_t host_uint16);
// returns host_uint32 convered to network byte order.
uint32_t htonl(uint32_t host_uint32);
// returns net_uint16_t convered to host byte order.
uint16_t ntohs(uint16_t net_uint16);
// returns net_uint32_t convertd to host byte order.
uint32_t ntohl(uint32_t net_uint32);
网络数据表示
在编写网络程序时,需要清除不同计算机架构使用不同的规则来表示各种数据类型。
由于在数据表现上存在这些差异,因此在网络中的异构系统之间交换数据的应用程序必须要采用一些公共规则来编码数据。发送者必须要根据这些规则来对数据进行编码,而接收者必须要遵循同样的规则对数据进行解码。
将数据编程一个标准格式以便在网络上传输的过程被称为信号编集(marshalling)
一种比信号编集更简单的方法通常被采用:将所有传输的数据编码成文本形式,其中数据项之间使用特定的字符来分隔开,这个特定的字符通常是换行符。
如果在遇到换行符之前读取的字节数大于或等于(n-1),那么readLine()函数会丢弃多余的字节(包括换行符);如果在前面的(n-1)字节中读取了换行符,那么在返回的字符串中就会包含这个换行符。(因此可以通过检查在返回的buffer中结尾null字节前是否是一个换行符来确定是否有字节被丢弃了)
另一种做法是让readLine()只读取足够的字节数来填充提供的缓冲器,而将到下一行新行为止的剩余字节留给下一个readLine()调用。
Internet Socket地址
Internet domain socket 地址有两种: IPv4 和 IPv6
IPv4 socket 地址 struct sockaddr_in
一个IPv4 socket地址会被存储在一个sockaddr_in结构中,定义如下
struct in_addr {
in_addr_t s_addr;
}
struct sockaddr_in{
sa_family_t sin_famuly;
in_port_t sin_port;
strcut in_addr sin_addr;
unsigned char _pad[X];
}
IPv4中sockaddr_in结构中的sin_family字段用于标识socket dimain,其值总为AF_INET
sin_port 和 sin_addr字段是端口号和IP地址,他们都是网络字节序的。
in_port_t 和 in_addr_t 数据类型是无符号整型,长度分别为16位和32位
IPv6 socket 地址 struct sockaddr_in6
与IPv4不同的差异在于IPv6是128位而不是32位的
struct in6_addr {
uint8_t s6_addr[16];
};