Série: Angelia
java
68 lignes
· Mis à jour 2026-09-27
EchoServer.java
Angelia/Java/Week_6_7/code/08_chat_protocol/EchoServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 最小的「一行一則訊息」伺服器:示範 Java 網路程式的基本骨架。
*
* 每收到一行,就用 ChatMessage.parse 解析;合法就回 OK(或 MSG 回送),不合法就回 ERR。
* 收到 QUIT 就回 BYE 並關閉該連線。
*
* 執行:java EchoServer 5555
* 另開一個終端機:java EchoClient localhost 5555 (或 nc localhost 5555 手動輸入)
*
* 注意:這個版本一次只服務一位客戶(單執行緒)。
* 要同時服務多位客戶需要「多執行緒」,那是 Week 8 Workshop 的主題。
*/
public class EchoServer {
public static void main(String[] args) throws IOException {
int port = args.length > 0 ? Integer.parseInt(args[0]) : 5555;
try (ServerSocket server = new ServerSocket(port)) { // 在 port 上「聽」
System.out.println("伺服器啟動,監聽 port " + port);
while (true) {
try (Socket client = server.accept(); // 阻塞直到有人連進來
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream(), "UTF-8"));
PrintWriter out = new PrintWriter(client.getOutputStream(), true, java.nio.charset.StandardCharsets.UTF_8)) {
System.out.println("客戶端已連線:" + client.getRemoteSocketAddress());
handle(in, out);
System.out.println("客戶端已離線");
}
}
}
}
/** 對「一個」客戶端的完整對話:一直讀到 QUIT 或連線中斷。 */
static void handle(BufferedReader in, PrintWriter out) throws IOException {
String name = null;
String line;
while ((line = in.readLine()) != null) { // readLine 回傳 null = 對方關閉了連線
ChatMessage reply;
try {
ChatMessage m = ChatMessage.parse(line);
switch (m) {
case ChatMessage.Login l -> {
name = l.name();
reply = new ChatMessage.Ok("welcome " + name);
}
case ChatMessage.Join j -> reply = new ChatMessage.Ok("joined " + j.room());
case ChatMessage.Say s -> reply = name == null
? new ChatMessage.Err(401, "login first")
: new ChatMessage.Msg(s.room(), name, s.text());
case ChatMessage.Quit q -> {
out.println(ChatMessage.encode(new ChatMessage.Bye()));
return;
}
default -> reply = new ChatMessage.Err(400, "clients may not send " + line.split(" ")[0]);
}
} catch (ChatMessage.ProtocolException e) {
reply = new ChatMessage.Err(400, e.getMessage());
}
out.println(ChatMessage.encode(reply)); // println 會加上換行並 flush
}
}
}
Articles liés
Angelia
haskell
EN
Mis à jour 2026-02-03
Adding.hs
Adding.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Adding.hs).
Lire l'article →
Angelia
haskell
EN
Mis à jour 2026-02-03
Area.hs
Area.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Area.hs).
Lire l'article →
Angelia
haskell
EN
Mis à jour 2026-02-03
Chess.hs
Chess.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Chess.hs).
Lire l'article →
Angelia
haskell
EN
Mis à jour 2026-02-03
ChessGraphics.hs
ChessGraphics.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/ChessGraphics.hs).
Lire l'article →
Angelia
haskell
EN
Mis à jour 2026-02-03
Examples.hs
Examples.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Examples.hs).
Lire l'article →
Angelia
haskell
EN
Mis à jour 2026-02-03
Fibonacci.hs
Fibonacci.hs — haskell source code from the Angelia learning materials (Angelia/Haskell/Fibonacci.hs).
Lire l'article →