楼主: JLpYOHze3CV2
63 0

[作业] Java基础教程之网络编程 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

小学生

14%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
40 点
帖子
3
精华
0
在线时间
0 小时
注册时间
2018-8-1
最后登录
2018-8-1

楼主
JLpYOHze3CV2 发表于 2025-12-3 07:02:56 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

本节学习目标

  • 理解多线程与网络编程之间的关联;
  • 掌握网络程序开发的主要架构模式;
  • 了解基于TCP协议的网络通信基本实现方式。

1. 网络编程的基本概念

在Java语言中,网络编程的核心目的在于实现不同主机之间的数据交换。为了简化这一过程,Java将其抽象为JVM(Java虚拟机)进程间的通信形式。即使在同一台物理设备上,也可以运行多个独立的JVM进程,这些进程在网络通信的语境下可被视为不同的主机节点。

图1 远程访问——JVM进程之间的交互示意图

每个JVM拥有独立的内存空间和系统资源,既可以在同一台机器上运行,也能分布于不同的物理设备中。借助Java提供的网络API,开发者能够在这些JVM之间建立连接,并进行数据的发送与接收操作。

采用JVM作为网络通信的基本单元具有显著优势。首先,它提供了更高层次的抽象模型,使网络通信的开发更加便捷高效。其次,当多个JVM运行在同一台主机时,它们之间的通信延迟更低,且可以共享部分本地资源,从而提升整体性能。

此外,在此前介绍的多线程编程内容中所涉及的并发机制,如线程调度、同步锁等技术,也为跨JVM的数据交互提供了安全保障,确保数据传输过程中的完整性与一致性。

不同JVM之间的数据访问本质上属于远程调用范畴。Java中的远程方法调用(RMI)以及企业级应用开发框架,正是基于此类通信机制构建而成。

Remote Method Invocation,RMI
JavaBean
Enterprise JavaBean, EJB

网络编程的本质是实现数据的双向交互。在此类通信过程中,通常会划分出两个角色:服务器端和客户端。根据实现方式的不同,主要存在以下两种典型架构模式:

C/S 架构(Client/Server)

该模式需要分别开发客户端和服务器端两套程序代码。由于两端都需要独立实现逻辑功能,因此在开发与后期维护方面成本较高。但其优点在于使用自定义端口和私有通信协议,安全性较强。

C/S架构下的网络通信依赖于两种基础传输协议:

TCP

TCP(传输控制协议):提供可靠的、面向连接的数据传输服务;

UDP

UDP(用户数据报协议):采用无连接方式,适用于对效率要求较高的场景。

B/S 架构(Browser/Server)

此模式无需单独开发客户端程序,仅需部署服务器端应用,用户通过浏览器即可完成访问。开发工作量较小,只需维护一套服务端代码。但由于使用公开的HTTP协议及默认80端口,安全防护能力相对较弱。

诸如

ASP
PHP
JSP

等技术均属于

B/S

的典型代表,这些技术的运行依赖特定服务器环境的支持。若要实现不同

B/S

组件间的互通,则必须借助

Web Service

相关技术支持。

关于 TCP 与 UDP 协议

TCP(传输控制协议) 提供的是可靠、面向连接的通信机制。在数据传输前,通信双方需通过“三次握手”建立稳定连接,确保链路通畅。TCP通过确认应答、超时重传、流量控制等机制保障数据不丢失、不重复、按序到达。

该协议适用于对数据完整性和顺序性要求较高的应用场景,例如网页请求(HTTP)、文件传输(FTP)、电子邮件等。

UDP(用户数据报协议) 则是一种无连接的通信协议,发送方无需事先建立连接即可直接发送数据包。由于省去了握手与断开连接的过程,UDP具备更低的延迟和更小的网络开销。

然而,UDP不保证数据的可靠性或顺序性,若发生丢包或乱序,需由应用程序自身处理恢复逻辑。因此,它更适合用于实时性优先、允许少量数据损失的场合,如在线音视频流、多人实时游戏、广播通信等。

在实际网络编程中,开发者可根据具体业务需求选择合适的传输层协议:

若强调数据的准确送达与顺序一致,则应选用

TCP

若追求低延迟并能接受一定程度的数据不可靠性,则可采用

UDP

。某些复杂系统甚至会同时集成两种协议,以分别处理关键数据与非关键实时数据。

2. Socket 与 ServerSocket 类详解

Java 中的

java.net

包封装了网络通信所需的核心工具类,其中最为关键的是以下两个类:

  • ServerSocket:专用于服务器端,封装了TCP协议的监听与连接接收功能,负责等待客户端发起连接请求;
  • Socket:表示一个客户端连接实例,同样基于TCP协议,用于与服务器进行数据读写操作。

以下是

ServerSocket

类常用方法说明:

方法名称 类型 描述
public ServerSocket(int port) throws IOException
构造方法 创建一个绑定指定端口号的服务器监听实例,建议使用5000以上的端口以避免冲突
public Socket accept() throws IOException
普通方法 阻塞式接收客户端连接请求,返回一个Socket对象用于后续通信
public void close() throws IOException
普通方法 关闭服务器监听,释放占用的端口资源

以下是

Socket

类的常用方法列表:

方法名称 类型 描述
public Socket(String host, int port) throws UnknownHostException, IOException
构造方法 创建Socket实例并连接到指定IP地址和端口号的目标服务器
public OutputStream getOutputStream() throws IOException
普通方法 获取输出流对象,通常包装为PrintStream以便发送字符串数据
public InputStream getInputStream() throws IOException
普通方法 获取输入流对象,用于读取来自服务器的数据
在TCP网络程序开发中,服务器端的设计是整个系统的核心部分。以下示例展示了一个基础的服务器端实现:每当有客户端连接时,服务器会向其发送一个固定的字符串信息“
Hello World
”。该服务监听本机的
9999
端口,通过调用
accept()
方法开启监听,等待客户端接入。 一旦客户端成功建立TCP连接,服务器便通过
PrintStream
将数据输出至客户端。数据传输完成后,服务器自动关闭。因此,此版本的服务仅能处理单次客户端请求,不具备持续服务能力。运行过程中程序会出现阻塞现象,直到客户端连接才会继续执行,如下图所示:

图2 客户端与服务器端交互 从客户端角度出发,需使用
Socket
类来发起连接请求。创建该类实例时,必须指定目标主机地址(如本地可用
localhost
或IP)和对应端口号。连接成功后,可通过
Scanner
获取输入流,从而读取来自服务器的数据响应。 服务器端接收到客户端连接后,会为其分配一个对应的
Socket
对象,代表当前会话的客户端实体。借助该对象,服务器可分别取得输入流与输出流,实现双向通信。为了提升IO效率,通常会对流进行包装处理,例如结合
Scanner
PrintStream
完成便捷的数据读写操作。 接下来介绍一个典型的网络编程实践案例——Echo回显程序。
Echo
模型在网络通信中具有代表性:用户在客户端任意输入内容并发送至服务器,服务器接收后添加前缀“
ECHO:
”再原路返回。为支持多次交互,服务不会在一次通信后立即关闭,而是持续运行,直至客户端发送特定终止指令(如“
byebye
”)才结束会话。 为实现上述功能,服务器端在接收到客户端连接后,立即获取其输入流和输出流,并利用
while
循环不断监听新消息、处理并回传结果。同样地,客户端也采用
while
循环控制输入行为,每输入一行文本即发送给服务器,除非内容为“
byebye
”,否则服务将持续响应。 尽管范例实现了基本的双端通信,但存在明显局限:它只能顺序处理一个客户端请求,无法并发响应多个连接。原因在于所有逻辑均运行于主线程中,属于典型的单线程架构。实际应用场景中,服务器往往需要同时服务大量客户端,为此应引入多线程机制。 如图所示,通过为每个新连接启动独立线程,可有效实现并发处理:

图3 多线程优化网络编程 具体实现中,每当有新的客户端接入,服务器便创建一个新线程专门负责该客户端的读写操作。主服务线程继续监听其他连接请求,互不干扰。这一设计显著提升了系统的并发能力与响应效率。
//	范例 5:修改服务器端
package com.xiaoshan.demo;

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

class EchoThread implements Runnable {
   
      	//建立线程类
	private Socket client;		//每个线程处理一个客户端
	
	public EchoThread(Socket client){
   
     	//创建线程对象时传递 Socket
		this.client = client;
	}
	
	@Override
	public void run(){
   
     
		try {
   
     			//每个线程对象取得各自Socket的输入流与输出流
			Scanner scan = new Scanner(client.getInputStream());
			PrintStream out = new PrintStream(client.getOutputStream());
			boolean flag = true;
			while(flag){
   
     		//控制多次接收操作
				if(scan.hasNext()){
   
     		//是否有内容
					String str = scan.next().trim();	//得到客户端发送的内容
					if (str.equalsIgnoreCase("byebye")){
   
     	// 程序结束
						out.println("拜拜,再见!");
						flag = false;				//退出循环
					}else{
   
     
						out.println("ECHO:"+str);	//回应信息
					}
				}
			}
			scan.close();
			out.close();
			client.close();
		} catch(Exception e){
   
     
			e.printStackTrace();
		}
	}
}

public class EchoServer {
   
     
	public static void main(String[] args) throws Exception{
   
     
		ServerSocket server = new ServerSocket(9999);	//在9999端口上监听
		boolean flag = true;                        	//循环标记
		while(flag){
   
                                	//接收多个客户端请求
			Socket client = server.accept();          	//客户端连接
			new Thread(new EchoThread(client)).start();	//创建并启动新线程
		}
		server.close();
	}
}
Java网络编程技术广泛应用于多种现实场景,主要包括以下几个方向: 1. **客户端-服务器通信** 借助Java的网络能力,可构建基于
C/S
模式的分布式系统。通过建立连接、传输数据及响应请求,实现浏览器与Web服务器间的HTTP交互、即时通讯工具等典型应用。 2. **文件传输与共享** 利用TCP协议建立稳定连接,可在不同节点间安全传输文件。常见应用包括FTP(文件传输协议)和SFTP(基于SSH的安全文件传输协议),适用于跨平台数据同步与资源共享。 3. **远程过程调用(RPC)** Java支持跨主机的方法调用机制,使分布式计算成为可能。开发者可使用Java RMI、Apache Thrift 或 gRPC 等框架,在不同设备上透明调用远程函数,支撑微服务架构的构建。 4. **Socket编程** Java提供的Socket API 允许开发者直接操控底层网络连接,支持TCP/UDP协议的自定义通信。此类技术常用于实时对战游戏、聊天系统等对延迟敏感的应用场景。 5. **网络爬虫与数据采集** 凭借强大的网络库支持,Java可用于开发高效的数据抓取工具。通过模拟浏览器行为,发送HTTP请求、解析HTML页面、提取关键信息并存储分析,广泛服务于舆情监控、价格比较、大数据采集等领域。
//	范例 3: 实现服务器端
package	com.xiaoshan.demo;

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class EchoServer {
   
     
	public static void main(String[] args) throws Exception {
   
     
		ServerSocket server = new ServerSocket(9999);		// 定义连接端口
		Socket client = server.accept();             	//等待客户端连接
		//得到客户端输入数据以及向客户端输出数据的对象,利用扫描流接收,打印流输出
		Scanner scan = new Scanner(client.getInputStream());
		PrintStream out = new PrintStream(client.getOutputStream());
		boolean flag = true;                          	//设置循环标记
		while(flag){
   
     
			if (scan.hasNext()){
   
     				//是否有内容输入
				String str = scan.next().trim();	//得到客户端发送的内容,并删除空格
				if(str.equalslgnoreCase("byebye")){
   
      	//程序结束标记
					out.println("拜拜,再见!"); 		//输出结束信息
					flag = false;					//退出循环
				}else{
   
     
					out.println("ECHO:" + str);		//回应输入信息,加“ECHO:” 前缀返回
				}
			}
		}
		scan.close();
		out.close();
		client.close();
		server.close();
	}
}

//	范例 4: 定义客户端
package com.xiaoshan.demo;

import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class EchoClient {
   
     
	public static void main(String[] args) throws Exception{
   
     
		Socket client = new Socket("localhost", 9999);       //服务器地址与端口
		Scanner input = new Scanner(System.in);                         //键盘输入数据
		//利用Scanner包装客户端输入数据(服务器端输出),PrintStream包装客户端输出数据
		Scanner scan = new Scanner(client.getInputStream());
		PrintStream out = new PrintStream(client.getOutputStream());
		input.useDelimiter("\n");	//设置键盘输入分隔符
		scan.useDelimiter("\n");	//设置回应数据分隔符
		boolean flag = true;		//循环标志
		while (flag){
   
     
			System.out.print("请输入要发送数据:");
			if(input.hasNext()){
   
     		//键盘是否输入数据
				String str = input.next().trim();	//取得键盘输入数据
				out.println(str);		//发送数据到服务器端
				if(str.equalsIgnoreCase("byebye"){
   
      	//结束标记
					flag = false;		//结束循环
				}
				if (scan.hasNext()){
   
     		//服务器端有回应 
					System.out println(scan.next());	//输出回应数据
				}
			}
		}
		input.close();
		scan.close();
		out.close();
		client.close();
	}
}

getInputStream()

getOutputStream()

//	范例 1: 定义服务器端——主要使用 ServerSocket
package com.xiaoshan.demo;

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class HelloServer {
   
     
	public static void main(String[] args) throws Exception {
   
     
		ServerSocket server = new ServerSocket(9999);    //所有的服务器必须有端口
		System.out.println("等待客户端连接…");            //提示信息
		Socket client = server.accept();                                       //等待客户端连接
		//OutputStream并不方便进行内容的输出,所以利用打印流完成输出
		PrintStream out = new PrintStream(client.getOutputStream());
		out.println("Hello World !");                                               //输出数据
		out.close();
		client.close();
		server.close();
	}
}

等待客户端连接…

//	范例 2: 编写客户端——Socket
package com.xiaoshan.demo;

import java.net.Socket;
import java.util.Scanner;

public class HelloClient {
   
     
	public static void main(String[] args) throws Exception {
   
     
		Socket client = new Socket("localhost", 9999);                       //连接服务器端
		//取得客户端的输入数据流对象,表示接收服务器端的输出信息
		Scanner scan = new Scanner(client.getInputStream());		//接收服务器端回应数据
		scan.useDelimiter("\n");	//设置分隔符
		if (scan.hasNext()){
   
     	//是否有数据
			System.out.println("【回应数据】"+ scan.next());	//取出数据
		}
		scan.close();
		client.close();
	}
}

【回应数据】Hello World !

C/S

网络编程在现代应用开发中具有至关重要的地位。它实现了不同主机之间的数据交换,为分布式系统的构建提供了基础支持。借助网络编程,开发者能够实现客户端与服务器之间的通信、网络爬虫与数据采集、文件的传输与共享,以及远程过程调用等多种功能。

本文围绕网络编程的基本概念及其相关协议展开介绍,重点分析了Java平台在网络通信方面的实现机制。我们深入探讨了Java中两个关键的网络编程类,分别是:

Socket
ServerSocket

这些核心API为构建网络连接和数据传输提供了必要的支持。

为了更直观地理解其工作原理,文章通过一个实战案例——Echo程序,演示了如何使用Java进行基本的网络通信。该示例展示了服务端接收客户端消息并原样返回的流程,帮助读者掌握Socket通信的基本结构和执行逻辑。

此外,还介绍了支撑网络通信的重要协议类型:

TCP
UDP

总体而言,无论是在Web应用开发还是分布式架构设计中,掌握网络编程技术都是开发人员不可或缺的能力。Java凭借其强大且丰富的网络库和API,支持多种通信协议与模式,为构建高效、稳定的网络应用程序提供了坚实的基础。通过深入理解这些技术原理并加以灵活运用,开发者可以应对多样化的应用场景需求,打造高性能的网络服务系统。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:java基础 网络编程 基础教程 Java jav
相关内容:Java编程基础

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-5 18:32