基本套接字函数

解说基本套接字函数,这里我们不考虑适用于服务器的大吞吐量并发性技术。

socket函数

为执行网络I/O,一个进程必须做的事情就是调用socket函数,指定期望的通信协议类型。使用IPv4的TCP、使用IPv6的UDP、UNIX域字节流协议等。

clip_image002

l 其中family参数指明协议族,或者称为协议域;

l type参数指明套接字类型;

l protocol参数应设为某个协议类型常值,或者设为0;

clip_image003

AF_INET:IPv4;

AF_INET6:IPv6;

clip_image004

SOCK_STREAM:TCP;

SOCK_DGRAM:UDP;

clip_image005

往往我们更多的使用一些组合:

clip_image007

基本函数流程:

 

调用socket的目的在于获取一个新建的socket句柄,该句柄需绑定了某种或多种协议,以及套接字类型

connect函数

使用connect函数来建立与TCP服务器的连接。

clip_image011

l sockfd是由socket返回的套接字描述符(句柄);

l servaddr是指一个指向套接字地址结构的指针;

l addrlen是指servaddr指向的地址结构大小;

套接字地址结构必须含有服务器的IP地址和端口号。

客户端在调用函数connect前不必非得调用bind函数,因为如果需要的话,内核会确定源IP地址,并选择一个临时端口作为源端口。

如果是TCP套接字,调用connect函数将激发TCP的三路握手过程,而且仅在连接建立成功或出错后才返回,其中出错返回可能有以下几种情况。

l 若TCP客户端没有收到SYN分节的响应(ACK),则返回ETIMEDOUT错误;

l 若对客户端的SYN的响应是RST(复位),则表明该服务器主机在我们指定的端口上没有进程在等待与之连接(简单说就是没有监听)。这是一种硬错误,则返回ECONNREFUSED错误。

l 若客户端发出的SYN在中间的某个路由器上引发了一个“destination unreachable”的ICMP错误,则任务是一个软错误。客户机内核保存该消息,并按照第一种情况中描述的时间间隔继续发送SYN。若在某个规定时间后仍未收到响应,则把保存的消息作为EHOSTUNREACH或ENETUNREACH错误返回给进程。

以下两种情况也是有可能的:一是按照本地系统的转发表,根本没有到达远程系统的路径;二是connect调用根本不等待就返回。

 

按照TCP状态图,connect函数导致当前套接字从CLOSED状态转移到SYN_SENT状态。若成功则再转移到ESTABLISHED状态。若connect失败则该套接字不可用,必须关闭,当然我们不能再次对同一个套接字再次调用connect函数。

bind函数

bind函数把一个本地协议地址赋予一个套接字。对于网际协议,协议地址是32位的IPv4地址或128位的IPv6地址,以及16位的TCP或UDP端口的组合。

clip_image015

l sockfd参数指的是创建的socket句柄;

l myaddr参数是一个指向特定于协议的地址结构的指针;

l addrlen参数是该地址结构的长度;

对于TCP,bind函数可以指定一个端口号,会指定一个IP地址,也可以两者都指定,还可以都不指定。

如果不绑定,当用户调用connect或listen时,内核就会自动选取一个随机的端口来和socket进行绑定。随机选择对于客户端来说是正常的,但对于服务器来说则不适合。

进程可以把一个IP绑定在套接字上,不过这个地址必须属于其所在的主机网络接口之一(即使是多网口)。

如果端口指定为0,那么内核就在bind被调用时选择一个临时端口。然而如果指定的IP地址为通配地址,那么内核将等到套接字已连接时才选择一个本地IP地址。

对于IPv4来说,通配地址由常值INADDR_ANY来指定

从bind函数返回的一个常见的错误时EADDRINUSE(地址已经使用);

另外SO_REUSEADDR和SO_REUSEPORT另外讨论;

listen函数

listen函数仅由TCP服务器调用,它做两件事:

当socket函数创建一个套接字时,它被假设为一个主动套接字,它被假设为一个主动套接字,它是一个将调用connect发起连接的客户端套接字。listen函数把一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该套接字的连接请求。

clip_image017

其中backlog参数,我们知道内核为任何一个给定的套接字维护两个队列:

未完成连接队列和已完成连接队列;所以该参数表示队列之和;所以建议这个值做的大点。

clip_image019

accept函数

accept函数由TCP服务器调用,用于从已完成连接队列对头返回下一个已完成的连接。

如果已完成连接队列已空,那么进程被投入睡眠(默认阻塞方式)。

clip_image021

cliaddr和addrlen用来返回已连接的对端进程的协议地址。如果accept成功,那么其返回值时由内核自动生成的一个全新描述符,代表与所返回客户端的TCP连接。

close/shutdown函数

用来关闭套接字,并终止TCP连接。

close一个TCP套接字的默认行为是把该套接字标记成关闭,然后立即返回到调用进程。

之后,该套接字描述符就不能在再被调用使用,也就是说不能再被作为read或write的第一个参数。

如果只是想关闭SOCKET上的某一个服务,比如读或写服务,那么可以使用shutdown函数。

l SHUT_RD    进程不能对指定套接口进行任何读操作

l SHUT_WR    进程不能对指定套接口进行任何写操作

l SHUT_RDWR    进程不能对指定套接口进行任何读、写操作

原文地址:https://www.cnblogs.com/davidsguo008/p/3591386.html