Unix网络编程——chap3

套接字编程简介

概述

socket编程的基础就是socket结构,几乎所有的API都会用到。而socket通常只会在两个方向上传递——进程到内核和内核到进程。

套接字地址结构

先看看IPV4的结构

1
2
3
4
5
6
7
8
9
10
11
struct in_addr {
in_addr_t s_addr;
};

struct sockaddr_in {
uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};

在sockaddr_in这个结构体,通常只需要三个字段: sin_family、sin_addr和sin_port(POSIX标准)。另外sin_zero这个字段一般不会使用,我们直接把其置为0即可

通常套接字地址结构,由于我们传递给socketAPI的是指针,所以这些API通常要处理各种支持不同协议的套接字地址,又因为套接字函数出来的时候,ANSI C还没有提出,也就无法使用通常指针void *。所以我们每次传入套接字函数,都需要转为以下的结构:

1
2
3
4
5
6
7
8
struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};

struct sockaddr_in serv;
bind(sockfd, (struct sockaddr *) &serv, sizeof(serv));

另外在IPv6提出之后,有了新的同样套接字地址结构,并且可以支持任何套接字结构,这里就不表了,可以搜一下:struct sockaddr_storage

值——结果参数

  • 从进程到内核传递套接字地址的函数有3个:bind, connect和sendto,参数是指向结构的指针,和结构的大小;

  • 从内核到进程传递套接字的函数有4个:accept, recvfrom, getsockname, getpeername,参数是指向结构的指针和直线结构大小变量的指针;

字节排序函数

这个是因为在不同的主机系统中,采用大小端模式是不同的,比如linux中是小端序,而apple中是大端序。这两种字节序转换用以下4个函数:

1
2
3
4
5
#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);

字节操作函数

没什么好说的,主要关注bzero,memset,memcpy等几个函数

inet_aton, inet_addr, inet_ntoa函数和inet_pton,inet_ntop函数

这些函数,是用来在ASCII字符串中和网络字节序的二进制值进行转换的。这两个函数——inet_pton,inet_ntop,针对IPv6和IPv4都是适用的。