在《网络编程-一个简单的echo程序(0)》和《网络编程-一个简单的echo程序(1)》中分别介绍了echo程序的整体流程和用到的数据结构与函数。本文将结合两者,来看实际使用过程中,有哪些基本的异常场景。
不支持的协议类型。前面在介绍socket函数的时候说到,TCP仅支持字节流套接字,UDP仅支持数据报套接字,如果你的第二个参数选择了SOCK_STREAM,即字节流套接字,而第三个参数选择了IPPROTO_UDP,那么将会出现不支持的协议错误。示例程序如下:
//来源 公众号【编程珠玑】 源网站:https://www.yanbinghu.com
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
int main(void)
{
int socktfd = socket(AF_INET,SOCK_STREAM,IPPROTO_UDP);
if(-1 == socktfd)
{
perror("socket failed");
}
return ;
}
运行结果:
socket failed: Protocol not supported
由于socket函数返回的是一个套接字描述符,因此它和打开文件一样,如果打开的数量到了一定的限度,也会出现失败。
除此之外,如果系统不支持某种协议族,例如不支持AF_KEY ,会出现:
Operation not permitted
的错误。
ip不存在。这种错误很容易模拟,还是用前文提到的server程序:
$ ./server 192.168.3.4
bind error: Cannot assign requested address
由于192.168.3.4并不是我本机的ip,因此在bind的时候必然会出错。
来源:公众号【编程珠玑】 网站:http://www.yanbinghu.com/2019/07/21/64710.html 作者:守望
端口已被占用,或者上一个没有停止。例如已经在一个终端启动了server,然后再次启动:
$ ./server
bind error: Address already in use
或者连接之后,server处于TIME_WAIT状态,此时再次启动server也会遇到相同的问题。
关于TIME_WAIT状态,在《网络编程-再看TCP的四次挥手》中有详细的论述,本文不再赘述。
出现这种错误的情况比较多,通常都是权限问题导致的,例如普通用户试图在1024以内的端口监听:
$ ./server 127.0.0.1
bind error: Permission denied
由于普通用户只能绑定使用1024以外的端口,因此当普通用户试图使用1024以内的端口时,就会提示Permission denied。
Permission denied的情况有很多种,这里只列举了其中一种。
这种错误在很多场景下会出现,因为我们在很多地方都用到了套接字描述符,因此一旦套接字描述符相关参数错误,都会出现这种错误,例如我们将bind的第一个参数随便指定一个值,并运行server:
$ ./server
bind error: Bad file descriptor
这个错误常常出现于连接到一个未监听的地址,例如:
$ ./client 127.0.0.1 8888
connect failed: Connection refused
这种情况下表明TCP连接的过程中收到了RST响应,有可能是8888端口没有监听,也可能是别的原因导致连接取消。
这个错误常常是由于远端服务器过于繁忙,没有accept。这个我们已经在TCP连接的建立一文中有说明,一旦服务端的连接队列满,将不会处理新的连接请求,客户端将会超时。
当然除此之外,如果指定连接到一个不存在的IP地址:
$ ./client 192.168.183.5
connect failed: Connection timed out
前面描述的情况只是很多情况的一两种,最终原因都是客户端没有收到SYN的响应,例如主机防火墙设置了端口不可访问,也可能导致出现这种情况。
如果是远端不可达的IP地址,将会收到主机不可达的ICMP错误:
$ ./client 192.168..
connect failed: No route to host
本文列出了在进行网络编程中最常遇到的错误,但远不止此;除此之外,某种错误出现的场景也并没有完全指出,但对于分析常见问题基本足够。当然也欢迎在留言区补充分享。