
为什么 ServerSocket accept() 会卡住,客户端连不上?
本质是服务端没真正监听成功,或者客户端连的是错地址。常见于 localhost 和真实 IP 混用、防火墙拦截、端口被占用。
- 启动前先用
netstat -an | grep :8080(Linux/macOS)或netstat -ano | findstr :8080(Windows)确认端口空闲 - 服务端别写
new ServerSocket(8080)就完事——得显式绑定new ServerSocket(8080, 50, InetAddress.getByName("0.0.0.0")),否则默认只绑127.0.0.1,局域网其他机器访问不到 - 客户端
new Socket("192.168.1.100", 8080)里的 IP 必须是服务端机器在局域网的真实 IP(用ipconfig或ifconfig查),不能填localhost或127.0.0.1
文件传输时为什么接收端只拿到前几个字节就结束了?
根本原因是没处理 TCP 流的边界:InputStream.read() 不保证一次读满缓冲区,而很多人直接拿 read(buffer) 返回值当“已读完”信号。
- 必须循环读,直到
read()返回-1(流结束)——尤其对文件这种大块数据 - 别用
available()判断是否读完,它只返回“当前可不阻塞读取的字节数”,不是文件总长 - 发送端关流顺序很重要:先
out.flush()再out.close(),否则最后一点数据可能卡在缓冲区里发不出去
用 DataInputStream / DataOutputStream 传文件靠谱吗?
不推荐。它们是为基本类型(int, double)设计的,底层仍调用 read()/write(),但额外加了类型校验和包装逻辑,对纯字节流反而多一层风险。
- 传文件直接用
BufferedInputStream+BufferedOutputStream,性能好、无歧义 - 如果真要用
DataOutputStream.writeUTF()发文件名,注意它最大只支持 65535 字节长度,超长路径会抛UTFDataFormatException - 别混用:服务端用
DataInputStream读,客户端却用普通OutputStream写——协议不匹配,读操作会一直等或直接报IOException
如何让传输过程不卡 UI,又避免多线程资源冲突?
核心是分离 I/O 和界面线程,但别裸写 Thread——容易漏关流、重复启停、状态失控。
立即学习“Java免费学习笔记(深入)”;
- 用
ExecutorService管理传输任务,比如Executors.newSingleThreadExecutor()控制并发数 - 每次传输新建独立的
Socket和流对象,别复用;流对象不可跨线程共享,更不能多个线程同时read()同一个InputStream - 进度回调别直接更新 Swing/AWT 组件——用
SwingUtilities.invokeLater()或 JavaFX 的Platform.runLater()包一层
try-with-resources,也得确认所有分支(包括 catch 块里)都覆盖到了,不然 socket 句柄泄漏,跑几次就 bind 失败。









