

我们就擦肩而过了
有趣
有用
有态度

导学问题:
1、套接字如何实现非阻塞调用?2、客户端能调用 bind 函数绑定端口吗?
服务端准备连接
创建一个套接字
int socket(int domain, int type, int protocol)domain : PF_INET:ipv4套接字 PF_INET6 :ipv6套接字 PF_LOCAL:本地套接字 ... type: SOCK_ATREAM:表示字节流,对应TCP SOCK_DGRAM:表示数据包,对应UCP SOCK_RAW:表示原始套接字 protocol:基本废弃,置0即可
如果执行成功,它会返回一个int类型的文件描述符
绑定套接字地址
bind(int fd,sockaddr *addr,socklen_t len)注意:关于套接字地址的类型介绍,可以查看我前面的其他文章。虽然这里接收的是通用地址格式,但实际上传入的参数可能是 IPv4、IPv6 或者本地套接字格式。因此bind 函数会根据 len 字段判断传入的参数 addr 该怎么解析,len 字段表示的就是传入的地址长度,它是一个可变值。
另外,网络环境中每台主机的ip地址都不相同,我们为了让程序运行在任意主机上,通常会在bind主机地址的时候,选择一个"通配地址"。对于 IPv4 的地址来说,使用 INADDR_ANY 来表示通配地址的设置,如下图:
struct sockaddr_in text;text.sin_addr.s_addr = htonl (INADDR_ANY); /* IPV4 通配地址 */fd:文件描述符 addr:套接字地址 len:套接字地址长度 监听套接字
初始化创建的套接字,默认是一个"主动"套接字,我们可以使用它去链接其他的主机(通过connect函数,稍后会介绍i)。但是,我们可以通过listen函数,使它化主动为被动,静静地等待其他主机来连接它。
int listen(int socket,int backlog)socket:文件描述符 backlog:可以监听的连接数量 套接字连接成功
当linux系统监听到客户端连接成功后,就需要把这个时间告诉给应用程序,好让应用程序开始进行收发工作。accept函数就是完成这个事情的。
int accept(int listensockfd,struct sockaddr *cliaddr,socklen_t *addrlen)accept函数本身也会返回一个新的套接字描述符,为什么这里有两个套接字呢?
主要原因是监听套接字必须要一直都存在,这样子我们才能够持续地监听客户端连接,而一旦新的客户端连接成功后,我们就要为它创建一个新的套接字,以后与该客户端的通信都将会通过这个套接字来实现
listensockfd:listen套接字,这是我们前面用socket函数创建的套接字 cliaddr:通过指针形式获取客户端地址 addrlen:获取地址的长度
客户端请求连接
前面讲述的bind、listen以及acept都是服务器端等待客户端连接的过程,下面我们来看客户端如何主动发起连接。
int connect(int fd,const struct sockaddr *servaddr,socklen_t addrlen)fd:使用socket函数创建的套接字接口 servaddr:套接字地址结构指针,在该地址中必须包含服务器的ip以及端口号 addrlen:套接字地址长度
客户端在调用connect函数前不一定要调用bind函数,如果没有bind函数,linux系统会自动为我们寻找一个空闲端口来使用。

END


扫码二维码
获取更多精彩
just enjoy it!

