Q:套接字特点
A:管道,消息队列,信号量,共享内存这些通信机制只能允许同一计算机上运行的进程相互通信,而套接字不仅可以提供在同一计算机上的进程间通信,还可以提供不同计算机上的进程间通信。
服务器端:
创建套接字描述符->将套接字与地址关联->监听套接字->接受链接
客服端:
创建套接字描述符->发起链接
创建套接字描述符
int socket(int domain, int type, int protocol);
domain: 通信特点,如AF_INET,IPv4因特网域
type: 套接字类型,如SOCK_STREAM字节流,SOCK_DGRAM数据报
type参数与下面标志相与:
SOCK_NONBLOCK创建非阻塞的socket
SOCK_CLOEXEC fork调用创建子进程时,子进程关闭该socket
protocol: 通常是0,选择默认协议。如果domain和type支持多个协议是,可以用
protocol指定一个特点的协议。
将套接字与地址关联
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);
将一个客户端的套接字关联上一个地址没有意义,可以让系统选一个默认的地址。所以如果调用connect或listen,但是没有将地址绑定到套接字上,系统会选一个地址绑定到套接字上。但是服务器端需要绑定一个地址,让客户端可以指定连接地址。
addr限制:
- 指定地址必须有效,端口号不能被占用,IP地址和计算机IP地址吻合
- 地址必须与创建套接字是的地址组协议相匹配
- 只能将一个套接字绑定到一个地址上
发起链接
int connect(int sockfd, const struct sockaddr *addr, socklen_t len);
如果用SOCK_DGRAM套接字调用connect,传送报文的目标会设置成connect调用中指定的地址,这样每次传送报文时就不用再提供地址额
监听套接字
int listen(int sockfd, int backlog);
服务器调用listen宣告它愿意接受连接请求
参数backlog仅作为一个提示,提示系统该进程所要入队的未完成链接请求数量,其实际值由系统决定。
接受链接
int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);
函数accept返回一个套接字描述符,该描述符连接到客户端,和原始套接字sockfd需要区分开来。如果不关心客户端标识,可以将参数addr和len设为NULL。
调用accept前,将addr参数设为足够大的缓冲区用来存放地址,len设为缓存区大小
返回时,accept会在缓冲区填充客户端的地址,并且更新len