I/O
TCP Server
net.createServer của Node.js so với net.Listen (Go), TcpListener (Rust), Network.framework (Swift) và ServerSocket (Java) để viết một TCP echo server.
- Phiên bản tối thiểu
- Node.js ≥ 12.20Go ≥ 1.0Rust ≥ 1.65Swift ≥ 5.7Java ≥ 25
- Đã chạy thử trên
- Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1
Code Node.js là ES module: lưu file .mjs hoặc đặt "type": "module" trong package.json.
Một TCP server chỉ cần: lắng nghe một port, chấp nhận kết nối, rồi đọc/ghi dữ liệu trên từng kết nối. Node.js xử lý mỗi socket bằng event, Go và Rust xử lý mỗi kết nối trong một thread/goroutine riêng (Rust không có goroutine — thread::spawn tạo hẳn một OS thread thật, tốn kém hơn; muốn nhẹ như goroutine phải dùng runtime async như tokio). Swift dùng Network.framework (Apple, không có socket API nào trong Foundation). Java 25 xử lý mỗi kết nối bằng một virtual thread (Thread.ofVirtual(), chính thức từ Java 21) — rẻ gần bằng goroutine, không cần thread pool.
Echo server
import net from 'node:net'
function handler(socket) {
socket.write('Received: ')
socket.pipe(socket)
}
const server = net.createServer(handler)
server.listen(3000)package main
import (
"bufio"
"net"
)
func handler(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
for {
message, err := reader.ReadString('\n')
if err != nil {
return
}
conn.Write([]byte("Received: "))
conn.Write([]byte(message))
}
}
func main() {
listener, err := net.Listen("tcp", ":3000")
if err != nil {
panic(err)
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
go handler(conn)
}
}use std::io::{BufRead, BufReader, Write};
use std::net::TcpListener;
use std::thread;
fn handler(stream: std::net::TcpStream) {
let mut writer = stream.try_clone().unwrap();
let reader = BufReader::new(stream);
for line in reader.lines() {
let Ok(line) = line else { break };
writer.write_all(b"Received: ").unwrap();
writer.write_all(line.as_bytes()).unwrap();
writer.write_all(b"\n").unwrap();
}
}
fn main() {
let listener = TcpListener::bind("0.0.0.0:3000").unwrap();
for stream in listener.incoming() {
let stream = stream.unwrap();
thread::spawn(move || handler(stream)); // một OS thread thật cho mỗi kết nối
}
}import Network
let listener = try NWListener(using: .tcp, on: 3000)
listener.newConnectionHandler = { connection in
connection.start(queue: .main)
receive(on: connection)
}
func receive(on connection: NWConnection) {
connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, isComplete, error in
if let data, !data.isEmpty {
connection.send(content: "Received: ".data(using: .utf8)! + data, completion: .contentProcessed { _ in })
}
if isComplete || error != nil {
connection.cancel()
} else {
receive(on: connection) // đọc tiếp gói tiếp theo
}
}
}
listener.start(queue: .main)
dispatchMain()void handle(Socket socket) throws Exception {
try (socket;
var reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
var writer = new PrintWriter(socket.getOutputStream(), true)) {
String line;
while ((line = reader.readLine()) != null) {
writer.println("Received: " + line);
}
}
}
void main() throws Exception {
try (var server = new ServerSocket(3000)) {
while (true) {
Socket socket = server.accept();
Thread.ofVirtual().start(() -> { // virtual thread, không phải OS thread thật
try {
handle(socket);
} catch (Exception e) {
// kết nối đóng hoặc lỗi
}
});
}
}
}$ echo 'hello' | nc localhost 3000
Received: helloTham khảo: github.com/miguelmota/golang-for-nodejs-developers#tcp-server