1.Socket概述
Socket是应用层与TCP/IP协议簇通信的中间软件抽象层,是一组接口。因为传输层和网络层协议由内核实现,所以又可以看成是用户进程与内核网络协议栈的编程接口。
socket通信过程如下图所示:
2.创建socket
函数定义为:
int socket(int domain, int type, int protocol);
函数返回socket描述符。3个入参。
(1)domain:协议域,又称为协议族(family)。常用的值:AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE等。
(2)type:指定socket类型。常用的类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。
(3)protocol:指定协议。常用的有:IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等。
当我们调用socket创建一个socket时,返回的socket描述符它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。
3.绑定端口
函数定义为:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
把地址簇中特定的地址赋给socket。3个入参。
(1)sockfd:socket描述符。
(2)addr:指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同。ipv4对应sockaddr_in;ipv6对应sockaddr_in6;Unix域对应sockaddr_un。
(3)addrlen:地址的长度。
4.监听端口
函数定义为:
int listen(int sockfd, int backlog);
此方法调用后,表示等待客户的连接请求。共2个入参。
(1)sockfd:要监听的socket描述字。
(2)backlog:相应socket可以排队的最大连接个数。
5.建立连接
函数定义为:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
客户端通过调用connect函数来建立与TCP服务器的连接。
共有三个入参:
(1)sockfd:客户端的socket描述字。
(2)addr:服务器的socket地址。参考bind函数的参数说明。
(3)addrlen:socket地址的长度。
6.接收请求
函数定义为:
int accept(int sockfd, struct sockaddr addr, socklen_t addrlen);
共有3个入参。
(1)sockfd:服务器的socket描述符。
(2)addr:客户端的socket地址。
(3)addrlen:协议地址的长度。
如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。
7.输入输出
根据不同的场景,实现了以下五对输出输出函数:
(1)read()/write()
(2)recv()/send()
(3)readv()/writev()
(4)recvmsg()/sendmsg()
(5)recvfrom()/sendto()。