目录
1. 网络基础
1.1 TCP/IP协议
1.2 网络的体系结构
1.3 TCP/IP协议族体系
1.4 网络预备知识
1.4.1 socket
1.4.2 IP地址
1.4.3 端口号
1.4.4 字节序
1.4.5 字节转换函数
1.4.6 TCP/UDP对比
2. TCP 编程 API
2.1 socket 函数
2.2 bind 函数
2.3 listen 函数
2.4 accept函数
2.5 客户端连接函数 connect
3. UDP 编程
3.1 send 函数
3.2 recv 函数
4. 并发服务器
应用层 | Relnet,FTP,HTTP,DNS,SMTP等 |
传输层 | TCP和UDP |
网络层 | IP,ICMP和IGMP,端到端传输 |
网络接口和物理层 | 以太网,令牌环网,FDDI,wifi,gps/2G/3G/4G,驱动(屏蔽硬件差异) |
是一个编程接口,是一个特殊的文件描述符(对他执行IO的操作函数,比如read,write,close等),并不仅限于TCP/IP协议,面向连接TCP,无连接UDP。
socket代表网络编程的一种资源
分类:
IP地址是Internet中主机的标识,Internet中的主机要与别的机器通信必须具有一个IP地址,IP地址为32为(Ipv4)或者128位(Ipv6),每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由
表示的形式:常用点分形式,如202.38.64.10,最后都会转化成一个32位的无符号整数
小端模式:将低序字节存储在起始地址
大端模式:将高序字节存储在起始地址
#include
uint16_t htons(uint16_t host16bitvalue); //返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue); //返回网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue); //返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvalue); //返回主机字节序的值
h代表host,n代表net,s代表short(两个字节),l代表long(4个字节),通过上面的4个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INADDR_ANY,INADDR_ANY指定地址让操作系统自己获取
#include include
int socket(int domain,int type,int protocol);
参数
domain
AF_INET
AF_INET6
AF_UNIX,AF_LOCAL
AF_NETLINK
AF_PACKET
type
SOCK_STREAM: 流式套接字,唯一对应于TCP
SOCK_DGRAM:数据报套接字,唯一对应着UDP
SOCK_RAW:原始套接字
protocol
一般填0,原始套接字编程时需填充
返回值
成功返回文件描述符
出错返回-1
如果是IPV6编程,要使用struct sockddr_in6结构体(man 7 IPV6),通常使用struct sockaddr_storage来编程。
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
参数
sockfd:通过socket()函数拿到的fd
addr:采用struct sockaddr的结构体地址,通用结构体
struct sockaddr{
sa_family_t sa_family;
char sa_data[4];}
struct sockaddr_in{ 基于Internel通信结构体
as_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
sin_zero , //填充字节,需清零
}
struct in_addr{
uint32_t s_addr;
}
addrlen:地址长度
一般情况下都是对 sockaddr_in 结构体进行初始化赋值,然后强制转换为 sockaddr 类型传入 bind 函数进行绑定。
int listen(int sockfd,int backlog);
参数:
sockfd: 通过socket()函数拿到的fd;
backLog:同时允许几路客户端和服务器进行正在连接的过程(正在三次握手),一般填5。
内核中服务器的套接字fd会维护2个链表
1.正在三次握手的客户端链表(数量=2*backlog+1)
2.已经建立好连接的客户端链表(已经完成三次握手分配好了的newfd)
返回值:
成功返回0
出错返回-1
listen(fd,5);//表示系统允许11(2*5+1)个客户端同时进行三次握手
阻塞等待客户端连接请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数
sockfd:经过前面socket()创建并通过bind(),listen()设置过的fd
addr:指向存放地址信息的结构体的首地址,获取客户端IP地址和端口号
addrlen:存放地址信息的结构体的大小
返回值
成功,返回返回已经建立连接的新的newfd
出错,返回-1
int connect (int sockfd, struct sockaddr * serv_addr, int addrlen)
参数:
sockfd:通过socket()函数拿到的fd
addr:struct sockaddr的结构体变量地址
addrlen:地址长度
返回值:
成功,返回0
失败,返回-1
bind:绑定服务器:TCP地址和端口号
receivefrom:阻塞等待客户端数据
sendto:指定服务器的IP地址和端口号,要发送的数据
ssize_t send(int sockfd,const void *buf,size_t len,int flags);
参数:
sockfd:socket函数返回的fd
buffer:发送缓冲区首地址
length:发送的字节
flags:发送方式(通常为0),作用和write一样
MSG_DONTWAIT,非阻塞
MSG_OOB:用于TCP类型的带外数据(out of band)
返回值:
成功:实际发送的字节数
失败:-1,并设置errno
int recv( SOCKET s, char FAR *buf, int len, int flags);
flag:一般填0,和read作用一样
特殊的标志:
MSG_DONTWAIT
MSG_OOB:读取带外数据
MSG_PEEK:流