《UNIX网络编程 卷1:套接字联网API(第3版)》——8.9 服务器进程未运行

简介: 我们下一个要检查的情形是在不启动服务器的前提下启动客户。如果我们这么做后在客户上键入一行文本,那么什么也不发生。客户永远阻塞于它的recvfrom调用,等待一个永不出现的服务器应答。然而这是一个很好的例子,它要求我们更多地了解底层协议以理解网络应用进程将发生什么。

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

8.9 服务器进程未运行

我们下一个要检查的情形是在不启动服务器的前提下启动客户。如果我们这么做后在客户上键入一行文本,那么什么也不发生。客户永远阻塞于它的recvfrom调用,等待一个永不出现的服务器应答。然而这是一个很好的例子,它要求我们更多地了解底层协议以理解网络应用进程将发生什么。

首先,我们在主机macosx上启动tcpdump,然后在同一个主机上启动客户,指定主机freebsd4为服务器主机。接着,我们键入一行文本,不过这行文本没有被回射。

macosx % udpcli01 172.24.37.94
hello, world            我们键入这一行
                    但没有任何内容回射回来

图8-10给出了tcpdump的输出。

screenshot

首先我们注意到,在客户主机能够往服务器主机发送那个UDP数据报之前,需要一次ARP请求和应答的交换。(我们把这个交换保留在tcpdump的输出中,是为了强调在IP数据报可发往本地网络上另一个主机或路由器之前,还是有可能出现ARP请求-应答的。)

我们从第3行看到客户数据报发出,然而从第4行看到,服务器主机响应的是一个"port unreach-able"(端口不可达)ICMP消息。(长度13是12个字符加换行符。)不过这个ICMP错误不返回给客户进程,其原因我们稍后讲述。客户永远阻塞于图8-8中的recvfrom调用。我们还指出ICMPv6也有端口不可达错误类型,类似于ICMPv4(见图A-15和图A-16),因此这里讨论的结果对于IPv6也类似。

我们称这个ICMP错误为异步错误(asynchronous error)。该错误由sendto引起,但是sendto本身却成功返回。回顾2.11节,我们知道从UDP输出操作成功返回仅仅表示在接口输出队列中具有存放所形成IP数据报的空间。该ICMP错误直到后来才返回(图8-10所示为4ms之后),这就是称其为异步的原因。

一个基本规则是:对于一个UDP套接字,由它引发的异步错误却并不返回给它,除非它已连接。我们将在8.11节讨论如何给UDP套接字调用connect。很少有人明白套接字最初实现时为什么做此设计决策。(实现内涵在TCPv2第748~749页讨论。)

考虑在单个UDP套接字上接连发送3个数据报给3个不同的服务器(即3个不同的IP地址)的一个UDP客户。该客户随后进入一个调用recvfrom读取应答的循环。其中有2个数据报被正确递送(也就是说,3个主机中有2个在运行服务器),但是第三个主机没有运行服务器。第三个主机于是以一个ICMP端口不可达错误响应。这个ICMP出错消息包含引起错误的数据报的IP首部和UDP首部。(ICMPv4和ICMPv6出错消息总是包含IP首部和所有的UDP首部或部分TCP首部,以便其接收者确定由哪个套接字引发该错误,如图28-21和图28-22所示。)发送这3个数据报的客户需要知道引发该错误的数据报的目的地址以区分究竟是哪一个数据报引发了错误。但是内核如何把该信息返回给客户进程呢?recvfrom可以返回的信息仅有errno值,它没有办法返回出错数据报的目的IP地址和目的UDP端口号。因此做出决定:仅在进程已将其UDP套接字连接到恰恰一个对端后,这些异步错误才返回给进程。

只要SO_BSDCOMPAT套接字选项没有开启,Linux甚至对未连接的套接字也返回大多数ICMP“destination unreachable”(目的地不可达)错误。图A-15中除代码为0、1、4、5、11和12之外的所有ICMP目的地不可达错误均被返回。

我们将在28.7节再次讨论UDP套接字上异步错误的这个问题,并给出一个使用我们自己的守护进程获取未连接套接字上这些错误的简便方法。

相关文章
|
11天前
|
数据安全/隐私保护
Haskell网络编程:代理服务器的高级使用技巧
Haskell网络编程:代理服务器的高级使用技巧
|
1月前
|
网络协议 算法 网络性能优化
C语言 网络编程(十五)套接字选项设置
`setsockopt()`函数用于设置套接字选项,如重复使用地址(`SO_REUSEADDR`)、端口(`SO_REUSEPORT`)及超时时间(`SO_RCVTIMEO`)。其参数包括套接字描述符、协议级别、选项名称、选项值及其长度。成功返回0,失败返回-1并设置`errno`。示例展示了如何创建TCP服务器并设置相关选项。配套的`getsockopt()`函数用于获取这些选项的值。
|
2月前
|
运维 算法 调度
深入理解操作系统:进程调度与优先级自动化运维:使用Ansible实现服务器集群管理
【8月更文挑战第27天】在操作系统的众多奥秘中,进程调度无疑是一个既简单又复杂的主题。它就像是交响乐团中的指挥,协调着每一个音符,确保乐曲和谐而有序地进行。本文将带领读者走进进程调度的世界,探索其背后的原理和实现,同时通过代码示例揭示其精妙之处。让我们一起揭开进程调度的神秘面纱,理解它在操作系统中的重要性。
|
2月前
|
C语言
【C语言】多进程服务器
【C语言】多进程服务器
18 4
|
2月前
|
网络协议 Java
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
这篇文章全面讲解了基于Socket的TCP网络编程,包括Socket基本概念、TCP编程步骤、客户端和服务端的通信过程,并通过具体代码示例展示了客户端与服务端之间的数据通信。同时,还提供了多个案例分析,如客户端发送信息给服务端、客户端发送文件给服务端以及服务端保存文件并返回确认信息给客户端的场景。
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
|
3月前
|
SQL 弹性计算 资源调度
云服务器 ECS产品使用问题之bin/spark-sql --master yarn如何进行集群模式运行
云服务器ECS(Elastic Compute Service)是各大云服务商阿里云提供的一种基础云计算服务,它允许用户租用云端计算资源来部署和运行各种应用程序。以下是一个关于如何使用ECS产品的综合指南。
|
3月前
|
关系型数据库 Java 分布式数据库
PolarDB产品使用问题之部署到服务器上的Java应用(以jar包形式运行)无法连接,如何解决
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
2月前
|
网络协议 Linux Shell
如何在运行Centos 6的虚拟服务器上安装cPanel
如何在运行Centos 6的虚拟服务器上安装cPanel
24 0
|
2月前
|
开发框架 Unix Linux
LangChain 构建问题之在Unix/Linux系统上设置OpenAI API密钥如何解决
LangChain 构建问题之在Unix/Linux系统上设置OpenAI API密钥如何解决
41 0
若依修改,若依部署在本地运行时的注意事项,后端连接了服务器,本地的vue.config.js要先改成localhost:端口号与后端匹配,部署的时候再改公网IP:端口号
若依修改,若依部署在本地运行时的注意事项,后端连接了服务器,本地的vue.config.js要先改成localhost:端口号与后端匹配,部署的时候再改公网IP:端口号
下一篇
无影云桌面