基本函数接口
socket函数
#include <sys/socket.h>
int socket(int family, int type, int protocol);
成功时返回一个非负整数,与文件描述符类似,称为套接字描述符 sockfd。各参数的意义:
-
family 指明协议族。取值为以下中的一个:
- AF_INET --> ipv4协议
- AF_INET6 --> ipv6协议
- AF_LOCOL --> Unix域协议
- AF_ROUTE --> 路由套接字
- AF_KEY --> 密钥套接字
-
type 指明套接字类型。取值为以下中的一个:
- SOCK_STREAM --> 字节流套接字
- SOCK_DGRAM --> 数据报套接字
- SOCK_SEQPACKET --> 有序分组套接字
- SOCK_RAW --> 原始套接字
-
protocol 设为某个协议类型常值。设为0时,选择所给定family和type组合的系统默认值。
- IPPROTO_TCP --> TCP传输协议
- IPPROTO_UDP --> UDP传输协议
- IPPTORO_SCTP --> SCTP传输协议
connect 函数
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
connect由客户端程序调用,用来建立与TCP服务器的连接。成功返回0, 出错返回-1
- sockfd 是socket()函数返回的套接字描述符
- servaddr 指向套接字地址结构的指针
- addrlen 套接字地址结构的大小
bind
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
bind把一个本地协议地址赋予一个套接字。对于网际网协议,协议地址是IP+端口号的组合。
对于服务器上的某个服务,如果把特定的IP和端口绑定到这个服务进程的套接字上,则客户端发过来的连接信息中目的地址和目的端口必须为这里指定的IP和端口。
对于客户端,如果绑定IP和端口到套接字上,则该套接字上发送的IP数据报指派了源IP地址。而客户端通常不做这些绑定,当要连接服务器时,内核为套接字选择一个临时端口,并根据外出网络接口来选择源IP地址。
listen
#include <sys/socket.h>
int listen(int sockfd, int backlog);
- 当socket函数创建一个套接字时,它被假设为一个主动套接字,将要调用connect去发起连接。listen可以把它转换为被动套接字,指示内核应该接受指向该套接字的连接请求。
- backlog 规定内核为相应套按字排队的最大连接个数。
内核为一个给定的监听套接字维护两个队列:
- 未完成连接队列
- 已完成连接队列
accept
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
accept()函数由TCP服务器调用,用于从已完成连接队列头返回下一个已完成连接。 如果已完成队列为空,则进程进入休眠。
cliaddr 返回已连接的对端进程协议地址结构,addrlen是对端协议地址结构的长度。
accept()成功则返回值是一个全新的描述符,代表与所返回客户端的连接,称为已连接套接字。
close
关闭套接字,内核中该套接字描述符的引用计数会减1。
习题
-
头文件<netinet/in.h>中定义的INADDR_常值是主机字节序的。我们应该如何辨别?
-
把图1-5改为在connect成功返回后调用getsockname。使用sock_ntop显示赋予TCP套接字的本地IP地址和本地端口号。你的系统的临时端口在什么范围内?
-
在一个并发服务器中,假设fork调用返回后子进程先运行,而且子进程承受后在fork调用返回父进程之前就完成对客户端的服务。图4-13中的两个close调用将会发生什么?
-
在图4-11中,先把服务器的商品号从13改为9999,再删掉listen调用,将会发生什么?
-
继续上一题,删掉bind调用,但是保留listen调用, 又将发生什么?