-
Notifications
You must be signed in to change notification settings - Fork 4
/
179.txt
94 lines (80 loc) · 2.99 KB
/
179.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
[1]
[[TCP]] の空いている ([[listen]] 可能な) [[ポート番号]]を取得したいことがあります。
[2]
例えば [[CI]] などで[[テスト]]プログラム用の[[サーバー]]プロセスを自動起動させたいとき、
[[ポート番号]]を決定する必要があります。
他の[[テスト]]と干渉しないように固定[[ポート]]ではなく、
動的に空き[[ポート]]を探したいです。
[3]
結論としては空き[[ポート]]を事前に知る可搬的な方法はないみたいです。
[4]
適当な[[ポート番号]]を選んで実際に [[listen]] してみて、
エラーになったら[[ポート番号]]を変えて再試行、
という方法がよく採られているようです。
[FIG[
[PRE(code)[
while (true) {
$port = get_random_port
$socket = listen $port
if (not $socket is failure) {
break;
}
}
]PRE]
]FIG]
[5]
[[ポート番号]]の決定と実際の [[listen]] が同じプロセスならそれでいいですが、
別の時 (例えばテストスクリプトでポート番号を決定して、
既製品のサーバーソフトウェアの設定ファイルを生成して起動する場合)
には、
[[listen]] に成功したらその[[ソケット]]を一旦 close
してからサーバープロセスを起動することになりますが、
その間に他のプロセスが[[ポート番号]]を奪ってしまうリスクが少しあります。
[FIG[
[PRE(code)[
while (true) {
$port = get_random_port
$socket = listen $port
if (not $socket is failure) {
break;
}
}
close $socket
run ("path/to/server", "--port", $port)
]PRE]
]FIG]
[6]
そのリスクを気にするなら、ポート番号を決定 → サーバーを起動
→ 起動失敗したらポート番号決定からやり直す、
となりますが、サーバー起動のオーバーヘッドが大きいときはしんどいです。
[FIG[
[PRE(code)[
while (true) {
$port = get_random_port
$result = run ("path/to/server", "--port", $port)
if (not $result is failure) {
break;
}
}
]PRE]
]FIG]
[7]
自動化された[[テスト]]のようなたまに失敗しても被害が出ないくらいのものなら、
現実的な[[競合条件]]のリスクを考えれば、 >>5 の方法で十分機能するみたいです。
[8]
[[ポート番号]]は
__&&[&&__[N[0]], [N[65535]]__&&]&&__
から選べますが、
[[特権ポート]]を使うと[[特権ユーザー]]
([CODE[root]])
以外が実行できなくなってしまいます。
従って
__&&[&&__[N[0]], [N[1023]]__&&]&&__
は避けるべきです。
[9]
なんとなく境界値は危うい気がするので、 [N[1024]] や [N[65535]] ([N[0xFFFF]])
も避けるのが無難そうです。
[10]
[[Webブラウザー]]から[[サーバー]]に接続するテストを想定すると、
[[Webブラウザー]]が [[fetch]] できない [[bad ports]]
も避けなければなりません。