您现在的位置是:焦点 >>正文

java socket编程

焦点8人已围观

简介java.net.Socket 这个类,表面上只是个构造方法加几个读写函数,但真正把它用好了,你才摸到网络编程的门槛。我见过太多人写服务端代码,上来就是 ServerSocket.accept() 死 ...

java.net.Socket 这个类,编程表面上只是编程个构造方法加几个读写函数,但真正把它用好了,编程你才摸到网络编程的编程门槛。我见过太多人写服务端代码,编程上来就是编程 ServerSocket.accept() 死循环,然后 new Thread 处理每个连接,编程最后线程池炸了,编程连接全断。编程这不是编程 Socket 的问题,是编程对它的生命周期理解太浅。

Socket 本质上是编程一条双向管道。你从一端写字节,编程另一端就能读到。编程但这条管道不是编程永久的,它受限于 TCP 协议的四次挥手、超时重传、还有内核缓冲区。一个最常见的坑是:你调了 outputStream.write(),数据未必立刻发出去,它可能还躺在本地缓冲区里。要强制发出去,得 flush()。可如果你写的是大文件,频繁 flush 又会拖垮性能,因为每次 flush 都可能触发一次网络往返。

我调试过一个支付网关的对接程序。对方服务端每收到一个请求,就回一个固定长度的响应,但客户端这边 read() 却永远读不完整。原因很简单——对方没有关闭输出流,而你在客户端用 read() 阻塞等待更多数据。TCP 是流协议,它不给你消息边界。你读到 10 个字节,不代表消息就结束了,除非对方关闭连接,或者你提前知道消息总长度。这个教训让我后来写 Socket 代码时,第一件事就是定义消息格式:要么固定长度,要么长度前缀,要么用特殊分隔符。

再谈连接断开。对方突然拔网线,你的 Socket 不会立刻感知,操作系统可能要等很久才发现 TCP 连接死了。所以你得自己设置读超时时间:socket.setSoTimeout(5000)。如果 5 秒内没数据进来,read() 会抛 SocketTimeoutException,你借这个机会主动发个心跳包,或者直接关闭连接重新连。别指望 TCP 的 keepalive 机制,默认要等两个小时才探测一次,对大多数业务来说太慢了。

端口占用是另一个经典问题。你关闭了 Socket,但端口可能还处于 TIME_WAIT 状态,要等几分钟才能重新绑定。服务器重启时尤其容易踩这个坑。解决办法是启动前设置 SO_REUSEADDR:serverSocket.setReuseAddress(true)。这行代码丢在开发环境里不痛不痒,但生产环境重启服务的时候,它能救你一条命。

说回性能。Java 传统的阻塞 IO 在连接数少的时候很直观,但几千个连接同时挂着,每个线程占 1MB 栈空间,内存就爆了。NIO 的 Selector 能在一个线程里管几千个通道,但代码复杂度陡增。我的建议是:如果你的连接数常年低于 200,老老实实用阻塞 IO 加线程池;如果真要做高并发网关,直接上 Netty,别自己手写 NIO 的 bug。

最后说个细节,很多人忽略。Socket 的输入输出流用完了要关,但关闭顺序有讲究。先关输出流,再关输入流,最后关 Socket 本身。如果你直接 socket.close(),有些未发送的数据可能被丢弃。正确做法是:outputStream.flush(); socket.shutdownOutput(); 等对方收到 EOF 后,你再读干净输入流里的剩余内容,然后才 close。这个顺序我栽过两次跟头,一次是文件传输丢最后几 KB,一次是 RPC 调用返回结果被截断。

Socket 编程没什么玄学,全是细节堆出来的。你踩过的每个坑,都是别人早就踩过的。把消息边界定清楚,把超时设短点,把关闭顺序写对,你的程序就能稳定跑上几年。剩下的,交给 JVM 和操作系统去操心吧。

Tags:

相关文章

  • 漏洞扫描工具离线版破解版

    焦点

    “离线版破解工具”这五个字,在安全圈里是个暧昧的存在。我见过最离谱的一次,是某甲方爸爸从QQ群搞来一个号称“全功能解锁”的Nessus离线包,装完一扫描,内网所有Windows主机全报“CVE-202 ...

    【焦点】

    阅读更多
  • 薅羊毛线报网

    焦点

    线报群的图标在凌晨三点突然跳动起来。我揉了揉眼睛,看见群主甩出一条链接:某电商平台生鲜区满199减100叠加五折券,折合一箱车厘子不到四十块。点进去,领券、下单、付款,整个过程不到两分钟。三天后,快递 ...

    【焦点】

    阅读更多
  • 二维码缺失一点点还能扫描吗

    焦点

    二维码缺了一角还能扫出来,这事我试过太多次了。前阵子手机屏幕摔裂,裂痕刚好横穿一个付款码的定位角,我捏着手机在便利店柜台前手心冒汗——结果“嘀”一声,支付成功。店员见怪不怪,说这码缺了三分之一都能用。 ...

    【焦点】

    阅读更多


友情链接