Java TCP Socket 编程实战:聊天室服务端与客户端实现

落日邮差
落日邮差
发布时间:2026-10-15 | 1人浏览过
原创

Java 网络编程中,Socket 是 TCP/IP 协议的核心抽象。本文将从概念入手,解析 Socket 的地址组成与连接机制,并通过服务端(ChatServer)和客户端(ChatClient)的完整代码,演示如何使用 InputStream 和 OutputStream 进行可靠的数据收发,重点说明 flush() 在强制刷新数据缓冲中的作用。

TCP Socket 核心概念与地址结构

Socket 是一个抽象层,应用程序通过它建立远程连接,底层由操作系统通过 TCP/IP 协议栈传输数据。之所以需要 Socket,是因为仅靠 IP 地址无法区分同一台计算机上运行的多个应用(如浏览器、QQ等)。操作系统通过 IP 地址 + 端口号(即 Socket 组合)来唯一标识一个网络连接。

端口号的分配规则如下:

  • 0~1023:特权端口,通常需要管理员权限(如 80, 443)。
  • 1024~65535:用户可用端口,普通应用程序可自由分配。

在网络通信模型中,服务器端需主动监听指定端口,等待客户端发起连接请求。连接成功后,双方将各自获得独立的 Socket 实体:服务器端的 Socket 对应固定监听端口,而客户端的 Socket 则使用动态分配的随机端口,从而确立一条全双工的 TCP 通路。

服务端实现:ChatServer

服务端的职责是创建监听对象、接受连接并响应数据。以下示例创建一个简单的对话服务端,监听端口 9966。

第1步:启动监听与预置数据

目的:初始化 ServerSocket 绑定端口,并准备映射字典用于回答。

package com.ljl.tcp.demo2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class ChatServer {
	public static void main(String[] args) {
		// 预置问答映射表
		Map<String, String> chatMap = new HashMap<String, String>(){
			{
				put("你好", "你好呀");
				put("hi", "hi~");
				put("hello", "哈喽");
				put("吃了吗", "没呢,你呢");
				put("孤勇者", "爱你孤身走暗巷");
				put("有请潘周聃", "潘周聃,今年29岁,苏黎世理工大学.....");
				put("很高兴认识你", "我也是哦");
			}
		};
		try (ServerSocket server = new ServerSocket(9966)) { // 监听9966端口
			while(true) {
				// 阻塞直到有客户端连接
				Socket client = server.accept();
				String clientIP = client.getInetAddress().getHostAddress();
				System.out.println("客户端连接成功: " + clientIP);
				try(
					BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
					BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));){	
					String question = reader.readLine();
					System.out.println("来自 " + clientIP + " 的提问:" + question);
					String answer = chatMap.get(question);
					answer = answer == null ? "我不知道你在说啥" : answer;
					writer.write(answer);
					//注意:此处未调用flush,依赖关闭流触发输出,实际生产建议显式flush
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

客户端实现:ChatClient

客户端需要主动连接服务器的 IP 和端口,发送消息并读取反馈。

第2步:建立连接与交互循环

目的:配置本地 IP(如 192.168.254.163),通过控制台输入发送请求,利用 shutdownOutput() 结束当前数据的写入通道以触发服务端读取。

package com.ljl.tcp.demo2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class ChatClient {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		while(true) {
			try (
				// 替换为目标服务器IP
				Socket client = new Socket("192.168.254.163",9966);
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));	
				BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
				){
				String question = input.nextLine();
				if("退下".equals(question)) break;
				
				// 发送请求
				writer.write(question);
				writer.flush(); // 重要:强制将数据推送到网络
				client.shutdownOutput(); // 标记写入结束
				
				String answer = reader.readLine();
				System.out.println("服务器回答:" + answer);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("over");
	}
}

数据流传输机制与注意事项

TCP 是面向连接的流协议,在 Java 中,Socket 实例提供了操作底层的 IO 流:

// 读取网络输入流
InputStream in = sock.getInputStream();
// 写入网络输出流
OutputStream out = sock.getOutputStream();

关于 Flush 的重要性: 在向网络写入数据时,系统会先将数据放入内存缓冲区。如果不调用 flush(),当缓冲区未满或程序结束时,数据可能滞留在内存中无法到达对端。因此,在每次 write() 后必须调用 flush() 以确保数据实时发送。

总结

  • 服务器端使用 ServerSocket 监听特定端口,调用 accept() 接收客户端。
  • 客户端使用 Socket(InetAddress, port) 发起连接。
  • 通信双方的读写均通过 Socket 的 InputStream 和 OutputStream 完成。
  • 数据写入后务必调用 flush() 清空缓冲区。

以上就是Java TCP Socket 编程服务端与客户端实现的详细内容,更多关于Java Socket教程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表