0 客户端-服务器结构
0.1 客户端和服务端位于同一台主机上
- 由于没有网络延迟,更容易判断客户端和服务器应用程序的原始性能
- 提供了理想的实验环境,分组不会被丢弃、延迟、传输时也不会失序
注意:如果施加足够的压力也会造成UDP报文丢失。
0.2 客户端和服务端位于同一局域网内的不同机器上
这种情况还是近乎理想,分组很少丢失,并且实际上不会出现错序的情况。
0.3 客户端和服务端被广域网隔开
两个应用程序不在同一个局域网中,从一个应用程序传向另一个应用程序的IP数据报必须经过一台或多台路由器。
随着流量的增多,用来在转发分组之前临时存储分组的路由器队列会被填满。路由器的队列空间耗尽时就开始丢弃分组,这就导致重传,重传又会导致分组的重复和乱序传输。
0.4 API
0.4.1 创建套接字
#include <sys/socket.h>
SOCKET socket(int domain, int type, int protocol);
0.4.2 建立连接
#include <sys/socket.h>
int connect(SOCKET s, const struct sockaddr* peer, int peer_len);
一旦建立连接后,就可以传送数据了。
0.4.3 绑定套接字
将接口地址和端口绑定到监听的套接字上去。地址为INADDR_ANY说明任何接口都会接受这个连接。
#include <sys/socket.h>
int bind(SOCKET s, const struct sockaddr* name, int namelen);
0.4.4 套接字监听
listen函数的唯一任务就是把套接字标识为监听状态。当主机收到一个连接请求时,内核会搜索监听套接字列表,查找与连接请求中目的地和端口号匹配的那个套接字。
#include <sys/socket.h>
int listen(SOCKET s, int backlog);
//backlog是排队等待应用程序接受的连接或部分连接的最大数值。
0.4.5 接受已完成连接队列中的连接accept
#include <sys/socket.h>
SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen);
//accept会在addr指向的sockaddr_in结构中返回新连接的对等实体地址。内核会将这个结构的长度存放在addlen指向的整数中。