根本原因是未按HTTP协议返回完整响应,必须包含状态行(如"HTTP/1.1 200 OK\r\n")、头字段、空行和正文,且编码、绑定地址、连接管理等均需严格符合规范。

用 ServerSocket 监听端口时,为什么浏览器打不开?
根本原因不是没监听,而是没按 HTTP 协议返回带状态行、头、空行、正文的完整响应。浏览器收不到 HTTP/1.1 200 OK 开头的报文,直接卡住或报 ERR_EMPTY_RESPONSE。
- 必须写
"HTTP/1.1 200 OK\r\n",不能只写"200 OK"或漏掉协议版本 -
\r\n是硬性要求,\n单换行会导致解析失败(尤其 Chrome) - 响应头之后必须有且仅有一个空行(即连续两个
\r\n),少一个或多一个都会让客户端无法识别正文起始 - 记得调用
socket.getOutputStream().flush(),否则缓冲区数据可能不发出去
手动解析 HTTP GET 请求要注意哪些字段?
实际只需要拆出三部分:请求行里的路径、Host 头(用于区分虚拟主机)、以及可选的 User-Agent(方便调试)。不需要完整实现 RFC7230 —— 简易服务器只处理 GET,忽略 POST、Connection: keep-alive 等复杂逻辑。
- 用
BufferedReader.readLine()逐行读,第一行是"GET /index.html HTTP/1.1",用空格切分取第二个元素即可得路径 -
Host头格式固定为"Host: localhost:8080",注意冒号后有空格,提取时要 trim - 遇到空行就停止读 header,后续内容属于 body(GET 请求 body 为空,可直接忽略)
- 别用
InputStream.readAllBytes()一次性读——HTTP 报文长度未知,容易阻塞
渲染 HTML 时怎么避免中文乱码?
核心是两处编码对齐:socket 输出流的字符集声明 + HTTP 响应头里的 Content-Type。Java 默认用平台编码(Windows 是 GBK),但浏览器默认按 UTF-8 解析,不显式声明就会乱码。
- 响应头必须包含:
"Content-Type: text/html; charset=utf-8\r\n" - 写响应体时,用
OutputStreamWriter(out, "UTF-8")包一层,别直接用PrintWriter(socket.getOutputStream()) - HTML 文件本身也得存成 UTF-8 编码(IDE 检查右下角编码标识),否则读文件时就错了
- 如果返回纯字符串(如
"<h1>你好</h1>"),确保字符串字面量在源码里是 UTF-8 保存,且编译时没加-encoding覆盖
为什么本地测试能通,但手机连不上?
大概率是绑定地址写死了 "127.0.0.1" 或 "localhost",导致只监听回环接口,外部设备无法访问。简易服务器没做权限和防火墙穿透,纯粹是网络层配置问题。
立即学习“Java免费学习笔记(深入)”;
- 创建
ServerSocket时,用new ServerSocket(8080)(无绑定地址)或new ServerSocket(8080, 50, InetAddress.getByName("0.0.0.0")) - 确认电脑防火墙放行该端口(Windows 防火墙入站规则;macOS 不限制;Linux 查
ufw status) - 手机和电脑必须在同一局域网,手机浏览器访问
http://[电脑局域网IP]:8080,不是localhost - Android 9+ 默认禁止明文 HTTP,若用
http://访问需在AndroidManifest.xml加android:usesCleartextTraffic="true"(仅调试)
真正麻烦的从来不是解析 HTTP,而是 TCP 连接管理——比如不关 socket 会导致端口占用、并发多请求时阻塞主线程、没有超时控制让坏连接一直挂着。这些在 Tomcat 里早被封装掉了,自己写就得一条条补。










