Skip to content

网络编程

网络基本知识

| A类

| B类

| C类

| D类

子网掩码

OSI模型

TCP/IP

套接字编程

创建套接字

#include <sys/socket.h>
int socket(int domain, int type, int flag);
/* 成功返回描述符,出错返回-1 */

参数domain确定通信的特性,包括地址格式,以AF_开头,意指地址族(address family

domain 描述
AF_INET IPv4因特网域
AF_INET6 IPv4因特网域
AF_UNIX UNIX域
AF_UPSPEC 未指定

参数type 确定套接字的类型

type 描述
SOCK_DGRAM 固定长度,无连接的,不可靠报文传递
SOCK_RAM IP协议的数据报接口
SOCK_SEQPACKET 固定长度,有序,可靠的,面向连接的报文传递
SOCK_STREAM 有序,可靠,双向,面向连接的字节流

参数protocol 通常是0,表示为给定的域和套接字类型选择默认协议

protocol 描述
IPPROTO_IP IPv4网际协议
IPPROTO_IPV6 IPv6网际协议
IPPROTO_ICMP 因特网控制报文协议
IPPROTO_RAW 原始IP数据包协议
IPPROTO_TCP 传输控制协议
IPPROTO_UDP 用户数据报协议

字节序

#include <arpa/inet.h>
uint32_t htonl (uint32_t hostint32);  /* host to net 返回网络字节序表示的32位整数 */
uint16_t htons (uint32_t hostint16);  /* host to net 返回网络字节序表示的16位整数 */
uint32_t ntohl (uint32_t netint32);  /* net to host 返回主机字节序表示的32位整数 */
uint16_t ntohs (uint16_t netint16);  /* net to host 返回主机字节序表示的16位整数 */

地址

linux中地址结构体定义如下

struct sockaddr {
    sa_family_t sa_family; /* address family */
    char        sa_data[14]; /* variable-length address */
};

IPv4因特网域(AF_INET)中地址结构表示如下

#include <netinet/in.h>
struct in_addr {
    in_addr_t s_addr;
};
struct scokaddr_in {
    sa_family_t sin_family;
    in_port_t   sin_port;
    struct in_addr sin_addr;
}

IPv6因特网域(AF_INET6)中地址结构表示如下

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; /* set of interfaces for scope */
}

它们会被强制转换成sockaddr输入到套接字的历程中

套接字与地址关联

#include <sys/socket/h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);

连接

int connect (int sockfd, const struct sockaddr *addr, socklen_t len);

这里的地址是想与之通信的服务器地址

int listen(int sockfd, int backlog);

服务器调用listen来宣告他愿意接受连接请求,listen 做两件事,

  1. socket创建套接字时,它被假设为一个主动套接字,listen函数将主动套接字换成被动套接字
  2. 本函数的第二个参数规定了内核应该为相应套接字排队的最大连接数
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

accept由服务器调用,用于从已完成连接的队列对头返回下一个已完成连接,如果队列为空,进程睡眠(默认)。如果accpet成功,返回值是内核自动生成的全新描述符

数据传输

ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
ssize_t recv(int sockfd, void * buf, size_t nbytes, int flags);

/* 面向无连接 指定目标地址 */
ssize_t sendto(int socked, const void *buf, size_t n_bytes, int flags,
               const struct sockaddr *destaddr, socklen_t destlen);

ssize_t recvfrom(int socked, const void *buf, size_t len, int flags,
               const struct sockaddr *srcaddr, socklen_t *srclen);
flag 描述
MSG_CMSG_CLOEXEC 为UNIX域套接字上接收的文件描述符设置执行时关闭标志
MSG_DONTWAIT 启用非阻塞操作(相当于使用O_NONBLOCK)
MSG_ERRQUEUE 接收错误信息作为辅助数据
MSG_OOB 如果协议支持,获取带外数据
MSG_PEEK 返回数据包内容而不真正取走数据包
MSG_TRUNC 即使数据包被截断,也返回数据包的实际长度
MSG_WAITALL 等待直到所有的数据可用(仅SOCK_STREAM)

套接字选项

套接字机制提供了两个套接字选项接口来控制套接字的行为,可以获取或设置一下3种

  1. 通用选项,工作在所有的套接字类型上
  2. 在套接字层次管理的选项,但是依赖于下层协议的支持
  3. 特定于某协议的选项,每个协议独有的
#include <sys/scoket.h>
int socksetopt(int sockfd, int level, int option, const void *val, socklen_t len);
int getsockopt (int sockfd, int level, int option, void *val, socklen_t *lenp);

SOL_SOCKET 应用层

选项名称 说明 数据类型
SO_BROADCAST 允许发送广播数据 int
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找路由 int
SO_ERROR 获得套接字错误 int
SO_KEEPALIVE 保持连接 int
SO_LINGER 延迟关闭连接 struct linger
SO_OOBINLINE 带外数据放入正常数据流 int
SO_RCVBUF 接收缓冲区大小 int
SO_SNDBUF 发送缓冲区大小 int
SO_RCVLOWAT 接收缓冲区下限 int
SO_SNDLOWAT 发送缓冲区下限 int
SO_RCVTIMEO 接收超时 struct timeval
SO_SNDTIMEO 发送超时 struct timeval
SO_REUSEADDR 允许重用本地地址和端口 int
SO_TYPE 获得套接字类型 int
SO_BSDCOMPAT 与BSD系统兼容 int

IPPROTO_IP IP层/网络层

选项名称 说明 数据类型
IP_HDRINCL 在数据包中包含IP首部 int
IP_OPTINOS IP首部选项 int
IP_TOS 服务类型
IP_TTL 生存时间 int
IP_ADD_MEMBERSHIP 将指定的IP加入多播组 struct ip_mreq

IPPRO_TCP 传输层

选项名称 说明 数据类型
TCP_MAXSEG TCP最大数据段的大小 int
TCP_NODELAY 不使用Nagle算法 int

面向连接的编程

面向无连接的编程

并发服务器

IO多路复用

多线程

广播与组播