QOJ.ac

QOJ

Limite de temps : 0.2 s Limite de mémoire : 32 MB Points totaux : 100

#6710. 外网

Statistiques

一家名为 Outdaters 的公司运营着一个小型计算机有线网络,称为 Outernet。与互联网不同,Outernet 并非基于 TCP/IP 协议。由于资金匮乏,Outernet 中的计算机并非都能直接相互通信。

Outdaters 已经找到了解决方案。他们创建了一种协议,使网络中的所有计算机都成为应用代理。应用代理可以从一台连接的计算机接收数据,并将其发送到另一台连接的计算机。因此,通过在 Outernet 中使用该协议,如果一台计算机想要向未直接连接的计算机发送信息,它必须将信息发送给一台连接的计算机/应用代理,并请求其帮助将信息转发给目的地或另一个连接的计算机/应用代理。

该协议描述如下:

A. 端口

应用代理使用端口来标识每一台连接的计算机。端口号是 0 到 32,767 之间的整数。对于应用代理而言,0 表示应用代理本身,其他每个端口号代表连接到该应用代理的一台唯一计算机。

B. 命令

应用代理仅接受 3 种命令(区分大小写):TO、DATA、QUIT。 对于每个传入的命令,应用代理在处理完该命令后,会向传入端口返回一行 3 位的结果代码。 格式:

xxx< LF > xxx -- the 3-digit result code

结果代码:

  • 100: OK。无错误/数据已路由至目的地
  • 101: OK。数据已路由至应用程序。(目标计算机即为应用代理本身。)
  • 200: 会话结束(对 QUIT 命令的响应)
  • 300: 未知命令
  • 301: 未知目的地
  • 302: 未开始会话
  • 303: 不允许循环(当传入端口 = 传出端口时)

各命令详情:

  1. TO:<目标计算机名称><LF>
    • 告知应用代理,后续数据需要发送至 <目标计算机名称>,并取消上一个 "TO" 命令的效果(向原目标计算机发送 "QUIT" 命令)。如果 TO 命令失败(结果代码既不是 100 也不是 101),应用代理的状态将不会改变。
    • 可能的结果代码:
      • 100: 在路由表中找到目标计算机,且不是应用代理本身。
      • 101: 在路由表中找到目标计算机,且正是应用代理本身。
      • 301: 在路由表中未找到目标计算机。
      • 303: 在路由表中找到目标计算机,但传入端口 = 传出端口。
  2. DATA<LF><数据><点 "."><LF>
    • 将 <数据> 发送至目标计算机。<数据> 将被视为数据流,如果目标计算机不是应用代理本身,则数据将原样发送至目的地。反斜杠 ("\") 是元字符,"." 表示一个简单的点 ".",而不是结束标志,"\" 表示 "\"。
    • 可能的结果代码:
      • 100: 在路由表中找到目标计算机,且不是应用代理本身。数据被路由至相应的传出端口。
      • 101: 在路由表中找到目标计算机,且正是应用代理本身。数据被路由至运行在此应用代理上的应用程序。
      • 302: 未开始会话,此命令被忽略。
  3. QUIT<LF>
    • 结束此通信会话。
    • 可能的结果代码:
      • 200: 会话结束(对 QUIT 命令的响应)
      • 302: 未开始会话,此命令被忽略。

C. 会话

当一台计算机(请求者)向应用代理发送 "TO" 命令时,通信会话开始;当向应用代理发送 "QUIT" 命令时,会话结束。在会话中,请求者可以向应用代理发送多个 "TO" 和 "DATA" 命令以发送多条消息。

应用代理能够同时处理来自不同端口的会话。

D. 路由表

每个应用代理都持有一个路由表。它使用该表来查找目标计算机名称应使用的端口。路由表中的每一行包含 2 个字段,第一个是目标计算机名称,第二个是传出端口号。这意味着,发送给具有该目标计算机名称的计算机的数据,将通过该传出端口号发送出去。端口号 0 表示数据应路由至运行在此应用代理上的应用程序;该目标计算机名称实际上就是应用代理的名称。

E. 路由

如果路由可行,应用代理使用相同的 "TO"、"DATA"、"QUIT" 命令来路由传入的数据。 在路由表中搜索后,如果找到了传出端口,应用代理必须为每个有效的传入 "TO" 命令在传出端口上创建一个完整的会话:开头一个 "TO" 命令,零个或多个用于路由数据的 DATA 命令,如果传入会话结束或收到另一个传入 "TO" 命令,则在最后发送一个 "QUIT" 命令。

端口 0 的处理方式与其他传出端口相同,只是不会实际发送传出命令,即所有命令的结果代码都将发送到传入端口,但不会向任何传出端口发送命令。 现在,Outdaters 聘请您编写引擎来实现该应用代理的协议。

输入格式

输入由一系列测试用例组成。每个测试用例以应用代理的路由表开始,随后是应用代理的传入请求。

路由表包括:一行包含一个整数 $M$ ($1 \leq M \leq 32\,768$),表示路由表中的行数;接着是 $M$ 行,每行包含一条路由信息。每条路由信息包含一个唯一的目标计算机名称(路由表中为 1 到 15 个字母数字字符)和一个传出端口号(0 到 32,767 的整数),中间用空格分隔,计算机名称区分大小写。

应用代理的传入请求包括来自已连接计算机的若干请求会话。一行以数字符号 "#" 开头,后跟一个整数 $P$ ($-1$, $1$ 到 $32\,767$),表示后续输入来自端口 $P$,$P < 0$ 表示测试用例结束。请求会话中的命令不会被 "#" 行中断。为简化输入处理,输入文件中的数据命令仅包含 "0"-"9"、"a"-"z"、"A"-"Z"、"@"、"#"、"_"、"+"、"-"、"*"、"/"、"\"、"?"、","、"." 和

输入以单个零结束。

输出格式

对于每个测试用例,按对应输入的顺序打印所有发送数据的端口的输出。对于每个端口的输出,一行以数字符号 "#" 开头,后跟一个整数 $P$ ($-1$, $1$ 到 $32\,767$),表示后续命令是在端口 $P$ 输出的,$P=-1$ 表示当前测试用例的输出结束。在 "#" 行之后是该端口输出的命令,直到遇到下一个 "#" 行。仅当需要更改端口号时才需要 "#" 行。

#< 端口号 >< LF >
在该端口输出的命令
#< 另一个端口号 >< LF >
在该端口输出的命令
...
#-1< LF >

样例

样例输入 1

5
RED 0
YELLOW 1
GREEN 2
BLUE 3
WHITE 3
#1
TO:GREEN
DATA
HELLO
.
#4
TO:WHITE
#1
Quit
QUIT
#2
TO:GREEN
DATA
A JOKE to myself
.
QUIT
#3
TO:ORANGE
QUIT
#4
QUIT
#-1
0

样例输出 1

#2
TO:GREEN
#1
100
#2
DATA
HELLO
.
#1
100
#3
TO:WHITE
#4
100
#1
300
#2
QUIT
#1
200
#2
303
302
302
#3
301
302
QUIT
#4
200

说明

表示 0xa。

Discussions

About Discussions

The discussion section is only for posting: General Discussions (problem-solving strategies, alternative approaches), and Off-topic conversations.

This is NOT for reporting issues! If you want to report bugs or errors, please use the Issues section below.

Open Discussions 0
No discussions in this category.

Issues

About Issues

If you find any issues with the problem (statement, scoring, time/memory limits, test cases, etc.), you may submit an issue here. A problem moderator will review your issue.

Guidelines:

  1. This is not a place to publish discussions, editorials, or requests to debug your code. Issues are only visible to you and problem moderators.
  2. Do not submit duplicated issues.
  3. Issues must be filed in English or Chinese only.
Active Issues 0
No issues in this category.
Closed/Resolved Issues 0
No issues in this category.