第一章第二节 socket基础API
创建socket
1 | /* |
命名socket
创建socket时,只给出了地址族,但是并未指定使用的具体socket地址,将一个socket与socket地址绑定称为socket命名。命名socket通常用在服务器端,这样客户端才知道该怎么连接该socket。而客户端通常不需要命名socket,采用匿名方式,即使用操作系统自动分配的socket地址。命名socket使用bind函数。
1 | /* |
常见的errno有两种:EACCES(被绑定的地址是受保护地址,仅超级用户可以访问。如普通用户将socket绑定到0-1023端口)与EADDRINUSE(被绑定的端口正在使用,如将socket绑定到处于TIME_WAIT状态的socket地址)。
监听socket
socket被命名后,还不能马上接受客户连接,需要使用listen函数来创建一个监听队列以存放待处理的客户连接。
1 | /* |
在Ubuntu18.04上测试,连接socket的连接最多可以有(backlog+1)个。
接受连接
accept函数从listen监听队列中接受一个连接。
1 | /* |
通过实验可知:accept只是从监听队列中取出连接,而不论连接处于哪种状态,更不关心网络状况的变化。
发起连接
客户端需要使用connect函数来主动连接服务器端的socket。
1 | /* |
常见的errno有两种:ECONNREFUSED(目标端口不存在)与ETIMEDOUT(连接超时)。
关闭连接
socket也是文件,因此也可以通过close函数关闭。事实上,close并非总是立即关闭一个连接,而是将socket的引用计数减1;只有当socket的引用计数为0时,才真的关闭连接。
1 | /* |
如果要立即终止连接,使用shutdown函数,它是专门为网络编程设计的。
1 | /* |