目录
参考书籍:
《UNIX环境高级编程(Advanced Programming int the UNIX Environment Second Edition)》
《TCP/IP详解 卷1:协议(TCP/IP Illustrated Volume 1 [Stevens 1994])》
《TCP/IP详解 卷2:实现(TCP/IP Illustrated Volume 2 [Wright and Stevens 1995])》
《TCP/IP详解 卷3:T/TCP、HTTP、NNTP及UNIX域协议(TCP/IP Illustrated Volume 3 [Stevens 1996])》
《UNIX网络编程 卷1:套接字联网API(UNIX Network Programming Volume 1: The Sockets Networking API)》
《UNIX网络编程 卷2:进程间通信(UNIX Network Programming Volume 2: Interprocess Communications)》
源码下载:
UNIX Network Programming, Volume 1, Third Edition Source Code
创建socket
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
参数解析:
- domain:套接字通信域;
- type:套接字类型;
- protocol:通常为0,表示按照给定域和类型选择的默认协议。
- AF_INET + SOCK_STREAN = TCP(传输控制协议);
- AF_INET + SOCK_DGRAM = UDP(用户数据报协议)。
套接字通信域:
域 | 描述 |
AF_INET | IPv4 |
AF_INET6 | IPv6 |
AF_UNIX | UNIX域,在UNIX系统中也称 AF_LOCAL |
AF_UNSPEC | 未指定 |
套接字类型:
类型 | 描述 | 备注 |
SOCK_DGRAM | 长度固定的,无连接不可靠的报文传递 | 数据报是一种自包含协议,与对方通信时不需要逻辑连接,填好地址后直接发送。 |
SOCK_RAM | IP协议的数据报接口(POSIX.1中为可选) | |
SOCK_SEQPACKET | 长度固定,有序,可靠的面向连接的报文传递 | |
SOCK_STREAN | 有序、可靠、双向的面向连接的报文传递 | 应用程序意识不到报文界限,因为是字节流,可能是多次函数调用才拿到所有报文。 |
套接字是双向的,允许通过函数shutdowm来禁止套接字上的输入和输出。
#include <sys/socket.h>
int shutdown(int sockfd, int how);
参数解析:
- sockfd:socket函数返回的文件描述符;
- how:禁用开关:
- SHUT_RD:关闭读
- SHUT_WR:关闭写;
- SHUT_RDWR:关闭读写。
字节序转换:
大端字节序(big-endian),小端字节序(little-endian)。
TCP/IP协议采用大端字节序,以下是字节序转换函数:
#include <arpa/inet.h>//老系统在<netinet/in.h>中
uint32_t htonl(uint32_t hostint32); //主机转网络,返回以网络字节序表示的32位整型数
uint32_t htons(uint32_t hostint16); //主机转网络,返回以网络字节序表示的16位整型数
uint32_t ntohl(uint32_t netint32); //网络转主机,返回以主机字节序表示的32位整型数
uint32_t ntohs(uint32_t netint16); //网络转主机,返回以主机字节序表示的16位整型数
Linux中,对于IPv4的套接字结构体定义:
struct in_addr
{
in_addr_t s_addr; /* IPv4 address */
};
struct sockaddr_in
{
sa_family_t sin_family; /* address family */
in_port_t sin_port; /* port number */
struct in_addr sin_addr; /* IPv4 address */
unsigned char sin_zero[8]; /* filler,默认全部置0 */
};
IPv6的套接字结构体定义:
struct in6_addr
{
uint8_t s6_addr[16];
};
struct sockaddr_in6
{
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};