《UNIX网络编程 卷1:套接字联网API(第3版)》——1.5 一个简单的时间获取服务器程序

简介: 通过填写一个网际套接字地址结构并调用bind函数,服务器的众所周知端口(对于时间获取服务是13)被捆绑到所创建的套接字。我们指定IP地址为INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任意网络接口上接受客户连接。

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

1.5 一个简单的时间获取服务器程序

我们可以编写一个简单的TCP时间获取服务器程序,它和1.2节中的客户程序一道工作。图1-9给出了这个服务器程序,它使用了上一节中讲过的包裹函数。

screenshot

创建TCP套接字
10 TCP套接字的创建与客户程序相同。

把服务器的众所周知端口捆绑到套接字
11~15 通过填写一个网际套接字地址结构并调用bind函数,服务器的众所周知端口(对于时间获取服务是13)被捆绑到所创建的套接字。我们指定IP地址为INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任意网络接口上接受客户连接。以后我们将了解怎样限定服务器进程只在单个网络接口上接受客户连接。

把套接字转换成监听套接字
16 调用listen函数把该套接字转换成一个监听套接字,这样来自客户的外来连接就可在该套接字上由内核接受。socket、bind和listen这3个调用步骤是任何TCP服务器准备所谓的监听描述符(listening descriptor,本例中为listenfd)的正常步骤。

常值LISTENQ在我们的unp.h头文件中定义。它指定系统内核允许在这个监听描述符上排队的最大客户连接数。我们将在4.5节详细说明客户连接的排队。

接受客户连接,发送应答
17~21 通常情况下,服务器进程在accept调用中被投入睡眠,等待某个客户连接的到达并被内核接受。TCP连接使用所谓的三路握手(three-way handshake)来建立连接。握手完毕时accept返回,其返回值是一个称为已连接描述符(connected descriptor)的新描述符(本例中为connfd)。该描述符用于与新近连接的那个客户通信。accept为每个连接到本服务器的客户返回一个新描述符。

本书全文采用的无限循环采用以下风格:

for ( ; ; ) {
    . . .
}

当前时间和日期是由库函数time返回的,它实际上返回的是自Unix纪元即0点0分0秒(国际标准时间)以来的秒数。下一个库函数ctime把该整数值转换成直观可读的时间格式,例如:

Mon May 26 20:58:40 2003
snprintf函数在这个字符串末尾添加一个回车符和一个回行符,随后write函数把结果字符串写给客户。

如果你尚不习惯改用snprintf代替较早的sprintf函数,那么现在是学习的时候了。调用sprintf无法检查目的缓冲区是否溢出。相反,snprintf要求其第二个参数指定目的缓冲区的大小,因此可确保该缓冲区不溢出。

snprintf相对较晚才加到ANSI C标准中,在称为ISO C99的版本中引入。不过几乎所有厂商都把它作为标准C函数库的一部分提供,而且另有许多免费可得的版本可用。我们贯穿全书使用snprintf,也推荐你出于可靠性考虑在自己的程序中改用它来代替sprintf。

值得注意的是,许多网络入侵是由黑客通过发送数据,导致服务器对sprintf的调用使其缓冲区溢出而发生的。必须小心使用的函数还有gets、strcat和strcpy,通常应分别改为调用fgets、strncat和strncpy。更好的替代函数是后来才引入的strlcat和strlcpy,它们确保结果是正确终止的字符串。编写安全的网络程序的更多技巧参见[Garfinkel, Schwartz, and Spafford 2003]的第23章。

终止连接
22 服务器通过调用close关闭与客户的连接。该调用引发正常的TCP连接终止序列:每个方向上发送一个FIN,每个FIN又由各自的对端确认。2.6节将详细讲述TCP的三路握手和用于终止一个TCP连接的4个TCP分组。

与上节查看客户程序一样,本节查看服务器程序也非常简略,具体细节留待本书以后论述。有以下几点需要注意。

与其客户程序一样,这一服务器程序也与IPv4协议相关。我们将在图11-13中给出使用getaddrinfo函数实现的一个协议无关的版本。
本服务器一次只能处理一个客户。如果多个客户连接差不多同时到达,系统内核在某个最大数目的限制下把它们排入队列,然后每次返回一个给accept函数。本服务器只需调用time和ctime这两个库函数,运行速度很快。然而如果服务器需用较多时间(譬如说几秒钟或一分钟)服务每个客户,那么我们必须以某种方式重叠对各个客户的服务。
图1-9中所示的服务器称为迭代服务器(iterative server),因为对于每个客户它都迭代执行一次。同时能处理多个客户的并发服务器(concurrent server)有多种编写技术。最简单的技术是调用Unix的fork函数(4.7节),为每个客户创建一个子进程。其他技术包括使用线程代替fork(26.4节),或在服务器启动时预先fork一定数量的子进程(30.6节)。

如果从shell命令行启动本例这样的一个服务器,我们也许想要它运行很长时间,因为服务器往往在系统工作期间一直运行。这要求我们往服务器程序中添加代码,以便它能够作为一个Unix守护进程(daemon)——能在后台运行且不跟任何终端关联的进程——运行。我们将在13.4节讨论守护进程。

相关文章
|
2月前
|
缓存 应用服务中间件 nginx
Web服务器的缓存机制与内容分发网络(CDN)
【8月更文第28天】随着互联网应用的发展,用户对网站响应速度的要求越来越高。为了提升用户体验,Web服务器通常会采用多种技术手段来优化页面加载速度,其中最重要的两种技术就是缓存机制和内容分发网络(CDN)。本文将深入探讨这两种技术的工作原理及其实现方法,并通过具体的代码示例加以说明。
87 1
|
2月前
|
监控 安全 数据挖掘
网络游戏服务器如何有效防护DDoS与CC攻击
随着网络游戏行业的蓬勃发展,其背后的服务器架构日益复杂,同时也面临着前所未有的网络安全威胁。其中,分布式拒绝服务(DDoS)和CC(Challenge Collapsar,一种针对网页的攻击方式)攻击尤为突出,它们通过大量伪造请求或恶意流量,使服务器资源耗尽,导致服务中断或响应缓慢。因此,保障网络游戏服务器的安全,有效防护DDoS与CC攻击,已成为游戏行业亟待解决的问题。
|
17天前
|
存储 弹性计算 测试技术
阿里云服务器实例规格vCPU、内存、网络带宽、网络收发包PPS、连接数等性能指标详解
阿里云服务器ECS实例可以分为多种实例规格族。根据CPU、内存等配置,一种实例规格族又分为多种实例规格。而实例规格又包含vCPU、处理器、内存、vTPM、本地存储、网络带宽、网络收发包PPS、连接数、弹性网卡、云盘带宽、云盘IOPS等指标,本文为大家详细介绍实例规格的这些指标,以供大家了解和选择。
阿里云服务器实例规格vCPU、内存、网络带宽、网络收发包PPS、连接数等性能指标详解
|
7天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
52 5
|
11天前
|
数据安全/隐私保护
Haskell网络编程:代理服务器的高级使用技巧
Haskell网络编程:代理服务器的高级使用技巧
|
1月前
|
网络协议 算法 网络性能优化
C语言 网络编程(十五)套接字选项设置
`setsockopt()`函数用于设置套接字选项,如重复使用地址(`SO_REUSEADDR`)、端口(`SO_REUSEPORT`)及超时时间(`SO_RCVTIMEO`)。其参数包括套接字描述符、协议级别、选项名称、选项值及其长度。成功返回0,失败返回-1并设置`errno`。示例展示了如何创建TCP服务器并设置相关选项。配套的`getsockopt()`函数用于获取这些选项的值。
|
23天前
|
存储 运维 网络协议
运维的基本概念:服务器和网络基础知识
运维的基本概念:服务器和网络基础知识
45 0
运维的基本概念:服务器和网络基础知识
|
2月前
|
网络协议 Java
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
这篇文章全面讲解了基于Socket的TCP网络编程,包括Socket基本概念、TCP编程步骤、客户端和服务端的通信过程,并通过具体代码示例展示了客户端与服务端之间的数据通信。同时,还提供了多个案例分析,如客户端发送信息给服务端、客户端发送文件给服务端以及服务端保存文件并返回确认信息给客户端的场景。
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
|
2月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
69 0
|
2月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
68 0
下一篇
无影云桌面