Java客户端必须用Socket而非ServerSocket建立连接,因后者仅用于服务端监听;Socket需显式设超时、用字节数组读写、包装BufferedReader处理换行,并通过异常捕获和资源关闭保障健壮性。

Java中创建TCP客户端用Socket而不是ServerSocket
很多人一看到“网络编程”就下意识用ServerSocket,其实那是服务端监听用的。客户端主动连接服务器,必须用Socket类实例化连接。
常见错误是写成new ServerSocket(8080)去连远程地址,结果抛出java.net.BindException: Address already in use——因为ServerSocket是在本机绑定端口监听,不是发起连接。
- 客户端连接示例:
Socket socket = new Socket("127.0.0.1", 8080); - 连接超时要显式设置:
socket.connect(new InetSocketAddress("example.com", 80), 5000); - 不设超时,
Socket默认阻塞直到建立连接或系统超时(可能长达数分钟)
InputStream和OutputStream不能直接读写字符串
Socket的getInputStream()返回的是字节流,read()方法返回int(-1表示流结束),不是字符;write()也只接受byte[]或单个int。直接传入"hello"会编译失败。
常见误操作:用socket.getOutputStream().write("hello"),报错cannot resolve method write(java.lang.String)。
立即学习“Java免费学习笔记(深入)”;
请注意以下说明:1、本程序允许任何人免费使用。2、本程序采用PHP+MYSQL架构编写。并且经过ZEND加密,所以运行环境需要有ZEND引擎支持。3、需要售后服务的,请与本作者联系,联系方式见下方。4、本程序还可以与您的网站想整合,可以实现用户在线服务功能,可以让客户管理自己的信息,可以查询自己的订单状况。以及返点信息等相关客户利益的信息。这个功能可提高客户的向心度。安装方法:1、解压本系统,放在
- 正确做法是转字节数组:
outputStream.write("hello\n".getBytes(StandardCharsets.UTF_8)); - 如果想按行读,得包装成
BufferedReader:BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
- 注意换行符:很多协议依赖
\n或\r\n作为消息边界,别漏写
服务端用ServerSocket accept后必须为每个连接启新线程或用NIO
ServerSocket.accept()是阻塞调用,一次只返回一个Socket。如果在主线程里直接read()处理,后续连接会被卡住,无法并发响应。
典型现象:第二个客户端连上来一直卡在connect(),服务端日志停在第一个请求处理中。
- 最简并发方案:每accept一个连接,就
new Thread(() -> handleConnection(clientSocket)).start(); - 但线程开销大,高并发下容易OOM,生产环境应改用
ExecutorService或java.nio.channels.ServerSocketChannel - 别忘了关闭资源:
clientSocket.close()、inputStream.close()等,否则文件描述符泄漏,跑一阵就报java.io.IOException: Too many open files
异常处理必须覆盖IOException和SocketTimeoutException
网络不稳定是常态,但新手常只捕获Exception或干脆忽略异常,导致连接中断后程序静默卡死或崩溃。
比如设置了socket.setSoTimeout(3000),读取超时时抛的是SocketTimeoutException(它是IOException子类),不是InterruptedException或RuntimeException。
- 必须显式处理:
try { int b = inputStream.read(); } catch (SocketTimeoutException e) { System.err.println("Read timeout, reconnecting..."); } catch (IOException e) { System.err.println("Connection broken: " + e.getMessage()); } -
Socket.isClosed()和Socket.isConnected()返回值有误导性:isConnected()只表示曾经连过,断连后仍返回true;判断是否可用得靠socket.getInputStream().read()是否抛异常
read()之后的判断和每次close()之前的检查里。









