《UNIX网络编程 卷1:套接字联网API(第3版)》——1.4 错误处理:包裹函数

简介: 任何现实世界的程序都必须检查每个函数调用是否返回错误。在图1-5所示的程序中,我们检查socket、inet_pton、connect、read和fputs函数是否返回错误,当发生错误时,就调用我们自己的err_quit或err_sys函数输出一个出错消息并终止程序的运行。

本节书摘来自异步社区《UNIX网络编程 卷1:套接字联网API(第3版)》一书中的第1章,第1.4节,作者:【美】W. Richard Stevens , Bill Fenner , Andrew M. Rudoff著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.4 错误处理:包裹函数

任何现实世界的程序都必须检查每个函数调用是否返回错误。在图1-5所示的程序中,我们检查socket、inet_pton、connect、read和fputs函数是否返回错误,当发生错误时,就调用我们自己的err_quit或err_sys函数输出一个出错消息并终止程序的运行。我们发现绝大多数情况下这正是我们想做的事。个别情况下,当这些函数返回错误时,我们想做的事并非简单地终止程序的运行,如图5-12所示,我们必须检查系统调用是否被中断了。

既然发生错误时终止程序的运行是普遍的情况,我们可以通过定义包裹函数(wrapper function)来缩短程序。每个包裹函数完成实际的函数调用,检查返回值,并在发生错误时终止进程。我们约定包裹函数名是实际函数名的首字母大写形式。例如,在语句

sockfd = Socket(AF_INET, SOCK_STREAM, 0);
中,函数Socket是函数socket的包裹函数,如图1-7所示。

screenshot

在本书中只要你遇到一个首字母大写的函数名,它就是我们定义的某个包裹函数。它调用的实际函数的名字与包裹函数名相同,不过以对应的小写字母开头。

然而在讲解本书中提供的源代码时,我们总是指称被调用的最低级别的函数(如socket),而不是包裹函数(如Socket)。

这些包裹函数不见得多节省代码量,但当我们在第26章中讨论线程时,将会发现线程函数遇到错误时并不设置标准Unix的errno变量,而是把errno的值作为函数返回值返回调用者。这意味着每次调用以pthread_开头的某个函数时,我们必须分配一个变量来存放函数返回值,以便在调用err_sys前把errno变量设置成该值。为避免引入花括号把代码弄得很混乱,我们可以使用C语言的逗号操作符,把errno的赋值与err_sys的调用组合成一条语句,如下所示:

int  n;

if ( (n = pthread_mutex_lock(&ndone_mutex)) != 0)
     errno = n, err_sys("pthread_mutex_lock error");

我们也可以为此定义一个新的错误处理函数,它取系统的错误号作为一个参数,不过通过定义如图1-8所示的包裹函数,我们可以让以上这段代码更为易读:
screenshot

Pthread_mutex_lock(&ndone_mutex);
要是仔细推敲C代码的编写,我们可以用宏来替代函数,从而稍微提高运行时效率,不过包裹函数很少是程序性能的瓶颈所在。

选择首字母大写一个函数名作为其包裹函数名是一种折中的方法。其他方法也考虑过,譬如给函数名加一个“e”前缀(如[Kernighan and Pike 1984]一书第182页所示),给函数名加一个“_e”后缀,等等。这些方法都能明显地提示调用了其他函数,但我们的这种风格看来是最少分散注意力的。

这种技术还有助于检查那些错误返回值通常被忽略的函数是否出错,例如close和listen。

本书后面的例子中,除非必须检查某个确定的错误是否发生,并以不同于终止进程的其他某种方式处理它,否则就使用这些包裹函数。书中不提供所有包裹函数的源代码,不过它们是可以免费获得的(见前言)。

Unix errno值
只要一个Unix函数(例如某个套接字函数)中有错误发生,全局变量errno就被置为一个指明该错误类型的正值,函数本身则通常返回1。err_sys查看errno变量的值并输出相应的出错消息,例如当errno值等于ETIMEDOUT时,将输出“Connection timed out”(连接超时)。

errno的值只在函数发生错误时设置。如果函数不返回错误,errno的值就没有定义。errno的所有正数错误值都是常值,具有以“E”开头的全大写字母名字,并通常在< sys/errno.n >头文件中定义。值0不表示任何错误。

在全局变量中存放errno值对于共享所有全局变量的多个线程并不适合。我们将在第26章中讲述解决这一问题的方法。

全书中我们将使用诸如“connect函数返回ECONNREFUSED”这样的句子简明表达以下意思:该函数返回一个错误(通常函数返回值为-1),同时errno被置为指定的常值。

相关文章
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
网络协议 开发工具
网络编程之 listen()函数的使用与三次握手的理解
listen()函数 在进入我们的函数讲解前大家再回顾一下编写服务器端的流程
440 0
|
5月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
7月前
|
存储 网络协议 API
Cpp网络编程Winsock API
本文详细介绍了使用Winsock API进行C++网络编程的过程,通过具体实例实现了一个基于TCP协议的C/S架构通信demo。文章从服务端与客户端两方面展开,涵盖网络库初始化、套接字创建、绑定IP与端口、监听与连接、数据收发到关闭连接等关键步骤。重点解析了`WSAStartup`、`socket`、`bind`、`listen`、`accept`、`connect`、`send`和`recv`等函数的使用方法及注意事项,并对比了标准库与Winsock库在链接时的区别。适合初学者了解Winsock网络编程基础。
335 35
|
7月前
|
人工智能 算法 安全
OpenRouter 推出百万 token 上下文 AI 模型!Quasar Alpha:提供完全免费的 API 服务,同时支持联网搜索和多模态交互
Quasar Alpha 是 OpenRouter 推出的预发布 AI 模型,具备百万级 token 上下文处理能力,在代码生成、指令遵循和低延迟响应方面表现卓越,同时支持联网搜索和多模态交互。
619 1
OpenRouter 推出百万 token 上下文 AI 模型!Quasar Alpha:提供完全免费的 API 服务,同时支持联网搜索和多模态交互
|
网络协议 Linux API
Linux网络编程:shutdown() 与 close() 函数详解:剖析 shutdown()、close() 函数的实现原理、参数说明和使用技巧
Linux网络编程:shutdown() 与 close() 函数详解:剖析 shutdown()、close() 函数的实现原理、参数说明和使用技巧
1633 0
|
人工智能 搜索推荐 API
用于企业AI搜索的Bocha Web Search API,给LLM提供联网搜索能力和长文本上下文
博查Web Search API是由博查提供的企业级互联网网页搜索API接口,允许开发者通过编程访问博查搜索引擎的搜索结果和相关信息,实现在应用程序或网站中集成搜索功能。该API支持近亿级网页内容搜索,适用于各类AI应用、RAG应用和AI Agent智能体的开发,解决数据安全、价格高昂和内容合规等问题。通过注册博查开发者账户、获取API KEY并调用API,开发者可以轻松集成搜索功能。
|
存储 Java Unix
(八)Java网络编程之IO模型篇-内核Select、Poll、Epoll多路复用函数源码深度历险!
select/poll、epoll这些词汇相信诸位都不陌生,因为在Redis/Nginx/Netty等一些高性能技术栈的底层原理中,大家应该都见过它们的身影,接下来重点讲解这块内容。
361 0
|
网络协议 Dubbo Java
【网络编程】理解客户端和服务器并使用Java提供的api实现回显服务器
【网络编程】理解客户端和服务器并使用Java提供的api实现回显服务器
167 0
|
存储 算法 网络协议
【探索Linux】P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )
【探索Linux】P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )
224 0

热门文章

最新文章