待检查:
您可能希望使用一个由关键区域和条件变量保护的结构(记录当前读和写操作的数量)来实施这一限制。
配置文件和命令行是至关重要的,必须完全按照指定的方式接受输入。请在提交工作之前,问命令行。
SIGHUP,那么服务器将重新读取配置文件(如果有的话),应用更改并重新启动正常操作。但是,d的任何变化都被忽略。还要注意,与正常启动(参见3.1节)不同,这次(新)参数是重新从配置文件中读取的,优先于命令行,包括对等体列表(根据新的配置文件专门设置)。
2.1同步
非开关参数是对配置文件中指定的对等体的添加(意味着它们将被添加到列表对等体中)。
唯一强制性的调试功能是与调试并发访问公告牌文件和公开对等通信相关的功能


程序功能:

公告栏消息和分布式协议:
在你开始工作之前,仔细阅读所有这些材料,确保你理解所有的要求。事实上,所有这些要求都反映在评分制度中。
内容
1、阶段1:公告板服务器
1.1应用协议
1.2性能及其他实现要求
1.3公告板文件
1.4并发管理
1.5启动和重新配置
2、阶段2:数据复制
2.1同步
2.2应用协议
3、实施和测试
3.1配置
3.2调试
3.3参考和分级计算环境
4、提交
4.1表示
4.2如何提交
5、级配
6、资源
介绍
这一挑战包括两个阶段。在第一阶段,您将构造一个简单的网络服务器。下一阶段将包括说服多个这样的服务器一起工作。在开始编写任何代码之前,请彻底阅读文档;文档中的所有内容都是规范的一部分,确保按照指定的方式实现整个服务器是您的责任。
这个挑战是为了让你有机会在POSIX1环境中展示你的系统编程技能。实际上,必须将服务器实现为UNIX服务(“守护进程”),而且还必须使用UNIX标准C库提供的POSIX API。因此,您的服务器必须用C或c++编写。
在整个讲义中,我们将引用以下配置参数。如何获得这些参数将在3.1节中描述。
bp是客户端-服务器通信的端口号(正整数),参见第1节;
sp是服务器间通信的端口号(正整数),见第2节;
bbfile是将在整个项目中操作的公告牌文件的名称(字符串),参见第1节;
Tmax是预分配的线程数(正整数),见章节1.4;
peers是参与同步的对等体列表(可能是空的主机名-端口号对列表),参见第2节;
d是一个布尔标志,控制服务器的启动,参见第1.5节;
D是一个控制调试工具的布尔标志,参见1.3节(最后一段)和3.2节。
1、阶段1:公告板服务器
您的第一个任务是构建一个简单的公告牌服务器。服务器从多个客户端接收一行消息,将它们存储在本地文件中,并根据请求返回。文件的名称由参数bbfile给出。消息在存储时由服务器建立的唯一编号进行标识,以及由消息的“发送者”(由下面解释的USER命令提供)。
客户端通过端口bp连接到我们的服务器。我们还假设有一个生产环境,以便实现并发控制。
1.1应用程序协议
由于互操作性的原因,网络应用程序使用严格的协议(称为应用程序协议)进行通信。本节概述了服务器使用的特定应用程序协议。固定宽度字体表示对于给定的命令或响应的文本是固定的,而可能变化的参数以斜体显示。
每个命令和响应都由一行文本组成。服务器应该处理字符'\n'和'\r'的任何组合作为行结束符,并且应该发送回以单个'\n'结束的响应。您应该能够使用telnet作为客户机或任何其他能够这样做的客户机来测试服务器,以发送和接收纯文本。
问候
在交互开始的时候,服务器向刚刚连接的客户端发送以下文本:
(0)0.0 问候语
其中,问候语是一些(可能是空的)信息,以欢迎客户。欢迎语文本没有特定的格式,但是强烈建议列出客户机可用的命令。
以免你疑惑,POSIX最初来自于“uniX的可移植操作系统接口”。随着时间的推移,标准被其他操作系统采用,所以“for uniX”部分不再相关。因此,许多人声称,如今POSIX代表“可移植的操作系统接口,在末尾加上一个X来表示酷”。
(1)USER 用户名
这个命令建立相应客户端发布的所有后续消息的用户名。用户名是一个不包含'/'字符的字符串。未来由各自的客户端发布的消息将被标识为按名称发布的消息。通常,客户端会发送这个命令,在会话开始时。但是服务器应该处理,特定客户端多次发送此命令,以及不发送一个USER命令(在这种情况下,发送者将是nobody)的情况。
服务器响应是一行:
1.0 HELLO 用户名 文本
其中的文本是一些(可能为空的)提示。
当用户名包含不可接受的字符时(包括但不限于'/')或其他不正确的响应是:
1.2 ERROR USER 文本
其中的文本是提示,并解释了处理请求时遇到的问题。

(2)READ 消息编号
该命令要求消息编号。如果该消息存在于公告板上,服务器将发送一行表单作为响应:
2.0 MESSAGE 消息编号 发送者/消息
其中消息表示请求的消息,前缀为发送者(由USER命令于张贴时生效)。
如果消息编号不存在,那么服务器发送这一行:
2.1 UNKNOWN 消息编号 文本
其中的文本是提示。
如果服务器在处理请求时遇到了内部错误(例如,公告板文件不可用),然后将以下响应发送回客户端:
2.2 ERROR READ 文本
同样,文本是没有特定结构的解释性信息。

(3)WRITE 消息
该命令将消息发送到服务器进行存储。服务器将把消息存储到公告板文件中,作为表单的一行:
消息编号/发送者/信息
其中message-number是由服务器分配的唯一编号,发送者是之前由客户端发出USER命令指定的用户名(如果该客户端没有发出USER命令,则为nobody)。存储成功后,服务器向客户端返回以下消息:
3.0 WROTE 消息编号
当存储过程中发生错误时,服务器用以下消息响应:
3.2 ERROR WRITE text
收到这样的响应必须保证没有消息被写入公告栏。

(3)REPLACE 消息编号/消息
该命令要求服务器删除消息编号,并将其替换为新消息(消息编号不变)。发送者也被更改为当前发送者,由之前的USER命令指定的用户名(如果没有发出这样的命令,则为nobody)。
服务器响应与WRITE命令的相同外,还有:
3.1 UNKNOWN 消息编号
当消息编号在公告板文件中不存在(即该文件中没有留言)。
(4)QUIT 文本
标志着互动的结束。在接收到此消息后,服务器将返回:
4.0 BYE 一些文本
并关闭socket。服务器给客户端提供了相同的响应(包括socket关闭),客户端只是关闭了它的连接。服务器总是以文明的方式关闭socket(在退出之前先关闭socket)。

1.2性能和其他实施要求

您的服务器必须是健壮的,在此意义上,当服务器终止时,不应丢失任何消息,除非可能有消息正在写入磁盘。应该认为公告板文件太大,不能完全保存在内存中。
您的服务器还必须是高效的,从某种意义上说,它不能在收到每条消息后重写整个公告板文件。它应该尽可能少地使用文件系统(在上述健壮性要求的范围内)。
现在还应该考虑并实现一种回滚最近事务(写入或替换)的机制。这将在作业的第二部分用到。
您必须构建一个并发服务器,它能够同时为许多客户机提供服务。您必须提供一个基于POSIX线程的实现,使用并发管理和线程预分配(如1.4节所述)。

1.3公告板文件
如果不存在,则必须创建配置文件或命令行中指定的公告板文件,并且必须重复使用(而不是覆盖)。分配消息编号根据收到WRITE请求的顺序,由服务器依次发送。没有两个消息在任何公告栏文件中有相同的号码。特别是,如果服务器是在现有文件上启动的,那么它应该在启动时检查该文件,并确保写入该文件的任何新消息都具有与现有消息编号不冲突的关联编号。
对公告板文件的访问控制遵循读/写范例,这是操作系统中一种常见的方案。必须允许不同执行线程同时读取公告板文件。但是,当线程写入公告板文件时,不允许进行其他操作(读或写)。当然,如果在多个读操作正在进行时发出了写请求,那么写操作将不得不等待当前读操作完成。注意,这种机制比普通的文件锁定稍微复杂一些。您可能希望使用一个由关键区域和条件变量保护的结构(记录当前读和写操作的数量)来实施这一限制。这种访问控制机制的低效实现将受到扣分。不要使用文件锁定来实现访问控制,因为此方法不能按预期工作。
显然,测试访问控制的正确实现是您的主要职责。然而,无论您选择如何执行测试,以下测试方法必须在您的提交中可用:
只要参数D为真:(a)应向标准输出提供打分读或写操作的开始和结束的适当消息,以及(b)应该使用适当的sleep()语句人为地延长每个读和写操作的时间(建议值:读操作为3秒,写操作为6秒)在各自的关键区域内。我将让您自己弄清楚这对调试访问控制有什么帮助。

1.4并发管理
服务器必须使用预先分配的线程。预分配的线程数为Tmax,因此Tmax也是对并发性的限制。

1.5启动和重新配置
当配置文件和命令行(参见3.1节)导致d的值为true时,服务器执行以下启动顺序:
1.绑定到指定的端口号,并执行任何必要的数据结构初始化。
2.设置合适的掩码。
3.为所有信号安装适当的信号处理程序。
4.退出当前进程组。
5.关闭所有文件描述符,并根据需要重新打开它们。特别是,控制台输出被重定向到位于当前工作目录中的文件bbserv.log。
6.从控制台分离。
7.将自己置于后台中。
8.检查并写入PID文件bbserv.pid位于当前工作目录中的Pid。
如果d为false,则不执行上述步骤:4、5、6和7。

服务器对SIGQUIT和SIGHUP信号的反应如下:关闭所有主socket,终止
在当前命令(如果有的话)完成后立即分配的所有预分配线程,然后关闭到所有客户机的所有连接。如果接收到的信号是SIGQUIT,则服务器终止。另一方面,如果正在处理SIGHUP,那么服务器将重新读取配置文件(如果有的话),应用更改并重新启动正常操作。但是,d的任何变化都被忽略。还要注意,与正常启动(参见3.1节)不同,这次(新)参数是重新从配置文件中读取的,优先于命令行,包括对等体列表(根据新的配置文件专门设置)。

2、阶段2:数据复制
我们现在已经准备好实现一个复制的数据库管理系统。因为我们已经有了它,所以我们将使用公告板文件作为我们的数据库。该文件现在在多个服务器上保持复制(和同步)。
每个服务器都会收到参与同步的其他服务器的列表。这是在配置文件和/或命令行中指定的列表对等体(参见章节3.1)。列表中的每个元素都由主机名和端口号组成。
此外,每个服务器在端口sp上侦听传入的同步请求。

2.1同步
事实上,这是一个复制的数据库,这对客户机是透明的。所有同行都有同样的能力,如前一节所述为客户提供服务。唯一可察觉的区别是写入或替换消息的请求的响应可能会延迟。任何USER、READ或QUIT请求都像以前一样在本地提供。服务器之间的同步是通过接收WRITE或REPLACE命令启动的,并使用两阶段提交协议来完成。该协议广泛应用于对数据一致性要求很高的应用场合。具体来说,该协议确保尽可能多的数据存储在每个节点副服务器是相同的,即使这会导致一些数据丢失。
当使用两阶段提交算法时,接收到WRITE或REPLACE命令的服务器成为主服务器(或协调器),其他服务器成为副服务器(或参与者)。顺便说一下,请注意主人变成了所有从机的客户。顾名思义,该算法由两个阶段组成:
预提交阶段master向所有对等体(列表对等体)广播一个“预提交”消息。可用于同步的服务器肯定地确认消息;服务器没有准备好(例如系统故障)将返回一个否定的确认。
主服务器阻塞(在某个超时内),直到它接收到所有确认。如果在主服务器超时之前没有应答,则假定为负应答。
如果存在一个否定的确认,主服务器发送一个"abort"消息给副服务器并终止写入操作(发送一个3.2 ERROR消息给相应的客户端)。从机们会,如果他们收到否定的答复,就放弃整个过程。
另一方面,如果所有确认都是正的,则启动协议的第二阶段。
在第二个阶段,主服务器向所有的副服务器发送一个“提交”消息,随后是当前操作进行所需的数据(即要执行的操作及其参数,你可以在提交消息本身或在一个单独的消息中发送)。
然后每个从机执行相应的操作。如果(本地)操作成功完成,则每个副服务器向主服务器发送一个肯定的确认,否则发送一个否定的确认。当且仅当从所有副服务器收到正向的ac确认信息时,主服务器执行请求的操作。当本地操作成功时,一个“成功”消息被发送到所有的从机。
如果有来自至少一个从机的否定确认,或者如果主成功了,那么主广播一个“不成功”的消息。在接收到这样的消息后,一个从机“撤销”写作过程,也就是说写作的效果被取消了。
如果进程成功,则向客户端发送一个合适的3.0 WROTE 消息,否则将发送一个3.2 ERROR消息代替。

总之,两阶段提交协议可以由两个有限自动机表示(一个用于主,另一个用于从),如图1所示(启用相应转换的条件用斜体和蓝色表示,而与转换相关的操作用纯文本表示)。
2.2应用程序协议
您负责为两阶段提交算法设计应用程序协议。在开始编写代码之前,最好考虑一下这种设计,这样您的协议就会更加健壮和明确。
该协议必须在提交文件中包含的名为protocol2pc.txt的文件中完整描述。
此外,当D为真时,服务器必须将所有与对等体交换的消息(已发送和已接收)打印到标准输出。请在该打印中指明哪些讯息已发出,哪些讯息已收到。
来自客户端的写请求
阶段1.广播PRECOMMIT
阶段2.收到PRECOMMIT
图1:两阶段提交协议中的主(上面)和从(下面)。

3、实施和测试
大多数实现需求已经在前面概述过了。唯一需要指定的主要事项是如何获得配置参数。我们还简短地讨论了调试的注意事项。

3.1配置
在启动时,我们的服务器读取一个配置文件。该文件包含由变量名组成的对以及该变量的值,用=字符分隔(没有空格)。配置文件包含以下定义(顺序不分先后):
THMAX=Tmax
BBPORT=bp
SYNCPORT=sp
BBFILE=bbfile
PEERS=peers
DAEMON=d
DEBUG=D
其中Tmax、bp和sp是表示正数的字符串,bbfile是一个文件名,d和D是布尔值,可以使用数字0和1或字符串false和true指定。对等体的列表由空格分隔的字符串组成。每个这样的字符串都有host:port形式,其中host是一个主机名(DNS名称或IP,点分十进制格式),port是一个正数。你可以假设对等点列表不包括当前服务器。您不需要在启动时验证对等体。相反,您只需要在需要同步时尝试连接到对等点;在预提交阶段,同步协议将处理任何畸形的对等体。
配置文件中的大多数行是可选的;每少一行会导致各自的变量接受一个默认值,如下:Tmax为20,bp为9000,sp为10000,peers为空列表,d为true, D为false。唯一的强制数据是bbfile;如果服务器不能从任意一个配置文件或命令行(见下文),那么它必须拒绝启动(并将适当的错误消息打印到标准输出)。服务器从不修改配置文件,即使配置文件丢失或不完整。
默认的配置文件名为bbserv.conf,位于当前目录下。这个名字可以由命令行选项-c覆盖,其参数指定(使用绝对或相对路径)用于各自会话的配置文件。
配置文件中提供的所有选项都可以使用命令行开关覆盖,如下所示:
-b根据参数覆盖(或设置)文件名bbfile
-t根据参数重写Tmax
-p根据参数重写端口号bp
-s根据参数重写端口号sp
-f(不带参数)强制d为false或0
-d(无参数)强制D为true或1

点分十进制格式将一个IP地址表示为一个4字节的序列,序列之间用点分隔。每个字节是一个十进制数(因此范围从0到255)。例如“207.162.99.36”为“linux.ubishops.ca”的当前IP地址。

任何非开关参数都被进一步解释为对等规范(因此必须具有如下形式host:port如上所述的端口)。
如果在配置文件和命令行上的开关都指定了某些选项,则命令行版本优先。另一方面,非开关参数是对配置文件中指定的对等体的添加(意味着它们将被添加到列表对等体中)。
理想情况下,命令行开关必须以任何顺序和任何组合指定(理想情况下,它们将使用getopt()解析)。但是,至少必须支持以下顺序:-b、-f、-d、-t, -p, -s, -c,后面跟着非开关参数。请注意,所有的开关都是可选的(这意味着可能缺少任何一个开关)。

3.2、调试
大多数(如果不是全部)现实生活中的服务器都包含调试工具,这有两个目的。首先,并发应用程序是出了名的难以调试,所以必须提供调试工具来促进这个过程。其次,如果服务器出现错误行为,相应的系统管理员通常会启用这些调试工具来识别和纠正问题,如果问题无法在本地解决,则会向开发人员提供有意义的数据。
在我们的例子中,调试功能是由参数D控制的。唯一强制性的调试功能是与调试并发访问公告牌文件和公开对等通信相关的功能(参见第1.3节和2.2节)。强烈建议在有此标志的情况下将产生的消息的总数量增加到标准输出。我没有具体的建议,但是我相信在整个开发过程中,你会发现为了调试服务器而需要打印信息;这些消息应该在正常操作期间被抑制,但我建议您在标志D存在的情况下重新启用它们。

3.3、参考和分级计算环境
您的服务器需要与标准telnet客户机以及发送和接收文本的任何其他客户机进行交互。因此,您应该能够处理使用通常的“\n”终止文本行的客户机,但也可以使用序列“\r\n”(telnet就是这样)。注意,实际上根据协议规范(请参阅第1.1节),您应该能够处理'\n'和'\r'的任何组合作为行结束符。
这个挑战的参考计算环境是linux.ubishops.ca,这意味着我将在此环境下编译和运行您的解决方案。这个环境是一个Linux机器,它提供了GCC的最新版本(目前是11.2.0,可能会更改)和GNU make(目前是4.3)。
也就是说,一个编写良好的解决方案应该构建并运行在任何合理的当前POSIX系统上,使用标准的C/ c++编译器(包括但不一定限于GCC和LLVM)和一个非古老版本的make (GNU或其他)。您可以使用任何当前的Linux发行版(确保安装了开发包)或Mac OS(安装了Xcode和Xcode命令行工具)轻松地设置这样的环境。这样的环境也可以在Windows上创建,但我无法提供建议,因为这超出了我的专业范围。然而,在提交之前(以防万一)在linux.ubishops.ca上测试你的解决方案仍然是一个好主意。
除了linux.ubishops.ca之外,以下机器将在5月15日这周的某个时间为您提供测试您的工作:
10.18.0.21 10.18.0.22 10.18.0.23
10.18.0.24 10.18.0.25 10.18.0.26
10.18.0.27 10.18.0.28 10.18.0.29
这些机器只能从linux.ubishops.ca访问(这意味着您必须首先连接到linux.ubishops.ca,然后从那里ssh到这些机器)。这些机器没有任何开发环境,因此您必须在linux.ubishops.ca上构建您的工作,然后才能在这些机器上运行它。
5月15日,您对这些机器的凭证将与linux.ubishops.ca相同;确保您在linux.ubishops.ca上的帐户正常工作,并知道该帐户的用户名和密码。然而,这些计算机是独立的,因此linux.ubishops.ca上的密码更改不会传播到任何其他计算机,并且在一台计算机上更改您的密码也不会传播到其他计算机。主目录也是相互独立的。
注意,这些机器很弱(每个机器只有1个CPU核心和1 GB RAM)。尝试平衡它们的使用可能是一个好主意(例如,如果你看到太多的人登录到一台那就换另一台),但只要你的程序运行得相当好,没有理由担心。
这些机器被认为是一次性的,这意味着它们可以在任何时候被重置到初始形态,而且没有任何警告。虽然在原则上,直到学期结束它们才会重置,但这不能保证,所以要确保你所有的数据都备份到其他地方。
尽管如此,请注意服务器的测试不需要多机器环境。您还可以在同一台机器上运行多个副服务器,但是在不同的目录下并绑定不同的端口号。然而,在多台机器上至少测试一次您的实现是一个好主意,这样可以消除在单机运行时不会出现的任何可能的bug。请注意,您将在一个多用户环境中工作,因此可以合理地假设每台机器将运行服务器的多个实例。因此,明智的做法是选择唯一的端口号。我建议您使用8000 +您的用户ID作为客户端服务的端口号,使用9000 +您的用户ID作为同步的端口号。以下两个shell命令在linux.ubishops.ca或任何一台登台机器上运行时会打印出这些数字:
echo $((8000+(id-u)))
echo $((9000+(id-u)))
更好的是,您可以在服务器的命令行中直接提供适当的端口号,如下所示:
./bbserv -p $((8000+(id-u)))) -s $((9000+(id-u))) -b bbfile
注意,如果您使用登台计算机,那么您应该限制自己使用9000和11000之间的端口号,因为其他端口号在防火墙级别被阻止。

4、提交
提交服务器的源代码以及相应的文档。注意,用于同步的应用程序协议的描述是文档的必要部分。

4.1表示
你的意见书必须包含以下内容:
1.你的工作代码。
2.一个合适的makefile。
在构建代码时,必须在提交的根目录下生成一个名为bbserv的可执行文件。在使用GNU make和GCC时,只需在提交的根目录的shell提示符处输入make,构建过程就必须成功完成。我建议您可以手工构建一个简单的makefile,但是生成的makefile也可以(只要它们在参考环境中工作就可以记录日志)。
还要提供目标清理,删除所有对象、可执行文件、日志和任何其他不必要的文件,从而将提交恢复到原始状态,准备构建和运行。
3.文档是提交的组成部分,应包括:
一个简短的“用户指南”,记录了对指定的人机界面或协议的任何偏差或添加(视情况而定)。不要重复规范,只记录偏差和/或添加。同时也要提供讲义中没有提到的代码所使用的所有算法的描述(或参考)。应该适当地赞扬您没有编写的代码和/或在您开始为这个挑战编码之前存在的代码。在这里描述你想出的任何不明显的实现方案。如果你用各种方法编写了一些聪明的代码,请记录下你的聪明(否则我可能会错过)。
代码中的适当注释,概述所有代码片段的功能,并参考上面关于算法和功能的部分。
文件protocol2pc.txt(参见章节2.2)。
如果文档(protocol2pc.txt的内容除外)的大小不能作为一个单独的文档,则可以将其包含在README文件中(见下文)。
所有文件应以纯文本形式提供;没有其他格式是可接受的。
4.一个README文件。
该文件必须命名为README(全部大写,没有扩展名),并且必须是纯文本。第一行必须包含所有合作者的名字,用逗号分隔。第二行必须包含以逗号分隔的电子邮件地址列表。准确地说,这一行的所有电子邮件地址将用于发送反馈您的提交;您可以指定任意数量的电子邮件地址。
文件的其余部分是自由格式的,包含您可能希望传达的任何信息。特别地,我建议在这里包含文档(参见上面),而不是在另一个文件中。

4.2如何提交
您的解决方案应该以电子方式提交,作为一个目录,其中依次包含您的工作。不要创建任何类型的存档;只需提交目录本身。提交目录的名称不需要遵循任何特定的格式。
以下提交方式是强制性的;以任何其他方式提交的工作将不会被打分。登录Linux.ubishops.ca,并使用以下命令提交:
submit cs590 dir
其中dir是要提交的目录。您可以通过相对路径或绝对路径指定它。还要注意“cs590”的大小写,这是必须注意的。
假设你的工作(代码、文档等)在~/networking/bbserv目录下,当前的工作目录是~/networking。然后你应该输入以下命令之一:
submit cs590 ~/networking/bbserv
submit cs590 bbserv
submit cs590 ./bbserv
输入man submit有更多细节。
重新提交和延迟提交
在截止日期内重新提交是可以的(只要发出上述命令,就像你想要的那样多次)。但请注意,只保留最近提交的内容。如果提交程序没有其他规定,逾期提交的作品将被接受,逾期一天将被处以20%的扣分。

5、定等级
打分过程将采用生产服务器。这样的服务器不应该偏离应用程序协议,通常应该按照指定的方式运行。大多数测试都是自动化的,所以愚蠢的错误可能会导致大量的分数损失(所以不要犯它们)。
打分是基于对新构建的代码进行的半自动测试。您的代码将只接受粗略的检查,以确保您已经观察到实现限制(如果适用),并建立代码所有权。糟糕的编程实践和肮脏的代码不会影响你的成绩,除非它们影响到程序的执行,或者在粗略的代码检查中很容易被注意到。
我将在几批标准化测试场景中构建并运行您的程序。第一批将运行服务器的空列表(因此测试阶段1),第二批将运行服务器的多个实例(因此测试阶段2)。我将使用我自己的配置文件复制到您的目录。所有这些大部分都是自动化的。因此,严格遵循构建过程和命令行是至关重要的。特别要注意的是,对命令行开关的理想处理是接受它们的任何顺序,但至少它们应该按照3.1节中指定的顺序接受。
因此,您的程序必须完全按照指定的方式构建,并且必须完全按照指定的方式接受输入。任何与构建规范或运行时输入需求(命令行参数、文件等)的偏差都将导致提交根本没有被打分,从而得到零打分。我不会在打分构建错误或运行时错误期间进行调试或修复,这些错误是由于不遵守给定的规范造成的;小错误的代价是非常大的,所以不要犯它们。如果有疑问,请在提交工作之前寻求帮助。
扣分将适用于所有与指定行为的偏差,包括但不限于应用程序协议的不正确实现、不正确的并发行为、繁忙等待循环和死锁。特别要注意的是,在网络应用程序中,任何通信都应该有一个相关的超时(以消除不可靠通信导致死锁的可能性)。
除此之外,请注意,两个(或更多)团队提交的相同或几乎相同的作品将被自动评为0分。我们会根据学系及大学的指引,进一步处理学术欺诈行为。
你所提交的各方面内容在最终成绩中的权重如下:

1.基本的客户机-服务器通信:30%。
2.公告板文件并发访问:20%。
3.点对点同步:30%。
4.超时、繁忙循环(或者更确切地说没有)、避免死锁等:10%。
5.信号处理:10%。

6、资源
熟悉POSIX和网络编程是您的责任。下面建议的资源可能会完成这一点,但我相信还有更多的资源存在。
TCP/IP网络栈的UNIX实现是Berkley sockets。CS464/564中描述了这一点以及其他标准api。本课程也提供并发和分布式应用程序的编程技术。特别感兴趣的部分包括课堂讲稿(幻灯片和录制的视频讲座)和代码示例。后一部分特别包含了一个归档文件,其中包括各种TCP实用程序,欢迎您使用(并且很可能使您的生活更轻松)。
在此基础上,手册页是一个非常有用的资源。在任何安装了开发人员工具的UNIX机器上,您都可以输入man function来获取function的详细描述(它可以是一个系统或库函数,但也可以是其他一些编程构造)。有时像上面这样的命令会产生错误的手册页。例如
man getopt
将生成UNIX命令getopt的手动页面,而不是同名的库函数。这是因为手动页面被分为有编号的部分,并且默认情况下返回第一次命中。假设getopt是一个shell命令,它在第1节中有一个手动页面,而库函数的手动页面(可能是您正在寻找的)在第3节中描述。为了在这种情况下获得正确的手册页,您必须显式地指定section号(在我们的示例中是3)作为第一个参数。因此,为您提供getopt函数的手动页面的命令是
man 3 getopt
注意,shell命令在第1节中描述,系统函数(OS API)在第2节中描述,标准C库函数在第3节中描述。有时很难立即实现哪个函数是系统函数,哪个是库函数;在这种情况下,唯一的办法是尝试两个部分。偶尔你可能需要去看第7节,这是Linux程序员手册的剩余部分。作为一个例子,信号在第7节中的手动页信号中进行了描述。
关于UNIX中的网络和系统编程的优秀介绍是《与TCP/IP的互联》,卷iii:客户机-服务器编程和应用程序,Linux/Posix Sockets版本(由Douglase.com和David L.Stevens, Prentice Hall, 2001)。这是本节开始提到的课程的实际基础。