黑马程序员——Java网络编程

------- android培训java培训、期待与您交流! ----------

常用的网络模型有两种:OSI参考模型和TCP/IP参考模型,OSI模型分七层分别为应用层、表示层、会话层、传输层、网络层、数据链路层和物理层,对应于TCP/IP模型的应用层、传输层、网络层和物理链路层。Java中的网络传输是基于套接字机制,要进行网络通信必须要指定通信三要素:IP地址、端口号以及遵循的传输协议类型。

一、网络通信三要素:

1、Java中使用InetAddress类对IP地址进行了封装,该对象提供了许多方便调用的静态方法,如getByName()、getAllByName(),getByAddress()、getLocalHost()等静态方法,获取对应主机的IP地址,返回类型为InetAddress或InetAddress[],同时该对象还提供了其他一些有用的非静态方法如getAddress(),getHostAddress()、getHostName()等能够很方便的获取相关信息。

2、端口号:它是用于标识网络应用程序进程的一种逻辑标识,通过它可以知道网络通信的对方是那个应用程序进程。

3、传输协议类型——常用的两个传输协议UDP和TCP,及用户数据报协议和传输控制协议。两者特点总结如下:

UDP:面向无连接的、不可靠的传输协议,而且对传输的数据报大小进行限制,最大不能超过64K,并且传输过程中不能保证数据一定能够到 达收信者,但其传输效率较高,通常用于一些实时性较强的网络通信中,比如实时聊天、视频等。

TCP:面向连接的、可靠的传输协议,保证传输过程中数据报一定到达收信者,而且连接过程要经历三次握手,对数据包的传输大小没有限制 ,可以进行大数据量的传输,但由于传输过程保证了数据的可靠性,使得其传输效率不如udp高,通常用于传输数据的应用程序。

二、网络编程——socket

socket是为了网络服务而提供的一种机制,通信的收发双方都有socket,网络通信实际上就是通信双方之间的socket的通信过程,数据在socket间是通过IO传输的。

1、UDP传输方式:两个重要的类——DatagramSocket用于发送和接收数据的套接字,DatagramPacket用于udp发送和接收数据时对数据包的封装。

udp传输方式进行网络编程的步骤:发送端——创建套接字对象,系统会为其随机分配一个端口号或者可以指定自己的端口号,然后,定义一个数据包,用于填装发送的数据,将发送数据写入数据报,定义一个DatagramPacket对象,将数据大包,并在其构造函数中指明发送端的IP和端口信息。最后,调用套接字的send方法,将数据发送到指定地点。

接收端:首先,定义一个套接字,并制定自己的端口号信息,用作标识发送端数据的目的地;然后,定义一个数据包用作接收数据,创建DatagramPacket对象,并调用套接字的receive方法,将发送来的数据打包给接收端的数据包。

import java.net.*;
import java.io.*;

/*
需求:在发送端通过键盘录入,将数据传输到接收端显示
该程序会对异常进行处理,而是直接抛出。
*/
class UdpChatSend
{
	public static void main(String[] args) throws Exception
	{
		//创建套接字对象
		DatagramSocket ds=new DatagramSocket();
		//通过键盘录入进行信息交互
		BufferedReader bufR=new BufferedReader(new InputStreamReader(System.in));
		//byte[] buf=new byte[1024];
		String line=null;
		while((line=bufR.readLine())!=null)
		{
			if("over".equals(line))
				break;
			//定义一个发送数据包
			byte[] buf=line.getBytes();
			//将发送数据打包给一个DatagramPacket对象,通过该对象指定发送目的端
			DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.158"),5001);
			//调用send发送将数据发往接收端即可,不保证发送的数据一定接收
			ds.send(dp);
			System.out.println("192.168.1.158"+"::"+line);
		}
		bufR.close();
		ds.close();
	}
}
class UdpChatRecv
{
	public static void main(String[] args) throws Exception
	{
		//创建接收端的套接字对象,并指定其端口号,标识接收方的进程
		DatagramSocket ds=new DatagramSocket(5001);
		byte[] buf=new byte[1024];
		while(true)
		{
			
			DatagramPacket dp=new DatagramPacket(buf,buf.length);
			//接收发送来的数据,
			ds.receive(dp);
			//通过DatagramPacket对象,获取发送来的数据
			String ip=dp.getAddress().getHostAddress();
			String str=new String(dp.getData(),0,dp.getLength());
			System.out.println(ip+"::"+str);
		}
		//ds.close();
	}
}

2、TCP传输方式:要分客户端和服务端,在客户端用Socket套接字,服务端则使用ServerSocket套接字进行通信,通过调用套接字的getInputStream()和getOutputStream()方法来获取套接字的输入流和输出流数据,在服务端通过一个阻塞方法accept来不断接受客户端的连接请求,并使用读写流等操作对客户端的数据进行读写操作处理。

步骤:

客户端:1、创建客户端Socket套接字,并将其与目的主机信息进行绑定

2、从数据源中读取数据并写入到套接字输出流中

3、读取套接字中由服务端传过来的确认信息

4、关闭套接字。

服务端:

1、创建服务端socket服务,并监听一个端口。

2、服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象。

3、可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。

4、如果通讯结束,关闭资源。注意:要先关客户端,再关服务端。

实例:校验登录名,服务端利用多线程技术,不断接收从不同客户端的连接请求,对每一个请求建立新的校验线程,判断用户名的正确性。

import java.net.*;
import java.io.*;
class LoginClient 
{
	public static void main(String[] args) 
	{
		try
		{
			//创建客户端套接字对象,并指定服务端地址信息
			Socket s=new Socket("192.168.1.158",5003);
			//创建读取键盘录入数据的流对象
			BufferedReader bufR=new BufferedReader(new InputStreamReader(System.in));
			//获取套接字输出流对象,将键盘数据写入到输出流
			PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
			//获取套接字输入流对象,读取服务端的反馈信息
			BufferedReader buffReader=new BufferedReader(new InputStreamReader(s.getInputStream()));
			String strLine=null;
			//最多有三次输入用户名的机会
			for(int i=0;i<3;i++)
			{
				strLine=bufR.readLine();
				if(strLine==null)
					break;
				pw.println(strLine);

				//读取服务端反馈信息
				String strBack=buffReader.readLine();
				if(strBack.contains("successed"))
				{
					System.out.println(strBack);
					break;
				}
				System.out.println(strBack);
			}
			s.shutdownOutput();
			s.close();
			
		}
		catch (Exception e)
		{
			throw new RuntimeException("Login failed!");
		}
	}
}

class LoginServer
{
	public static void main(String[] args)throws Exception
	{
		ServerSocket ss=new ServerSocket(5003);
		while(true)
		{
			Socket s=ss.accept();
			new Thread(new LoginThread(s)).start();
		}
	}
}
class LoginThread implements Runnable
{
	private Socket s;
	LoginThread(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		String ip=s.getInetAddress().getHostAddress();
		try
		{
			

			for(int i=0;i<3;i++)
			{
				//读取硬盘中保存的用户数据信息
				BufferedReader bufR=new BufferedReader(new FileReader("user.txt"));
				BufferedReader bufS=new BufferedReader(new InputStreamReader(s.getInputStream()));

				PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
				String names=null;
				String name=bufS.readLine();
				//匹配结束标志
				boolean bMatch=false;
				while((names=bufR.readLine())!=null)
				{
					if(name.equals(names))
					{
						bMatch=true;
						break;
					}
		
				}
				if(bMatch)
				{
					System.out.println(ip+"Login!");
					pw.println("Login successed!");
					break;
				}
				else
				{
					System.out.println(ip+"failed!");
					pw.println("Login failed!");
				}
			}
			s.close();
			
		}
		catch (Exception e)
		{
			throw new RuntimeException("Login failed!");
		}
	}
}


内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
### TCP传输原理与实现 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。其核心原理是通过建立端到端的连接,确保数据在不可靠的网络中能够可靠地传输。TCP 使用确认机制、流量控制、拥塞控制等机制来保障数据的完整性和有序性。 在 Java 中,TCP 通信可以通过 `Socket` 和 `ServerSocket` 类实现。客户端使用 `Socket` 连接到服务器,服务器端使用 `ServerSocket` 监听连接请求。通信过程中,数据通过输入流和输出流进行传输。 #### 客户端实现 客户端的主要任务是与服务器建立连接,并通过输出流向服务器发送数据,同时可以通过输入流接收服务器的响应。例如: ```java Socket s = new Socket(InetAddress.getLocalHost(), 10004); OutputStream out = s.getOutputStream(); out.write("Hello TCPClient".getBytes()); InputStream is = s.getInputStream(); byte[] buffer = new byte[1024]; int len = is.read(buffer); System.out.println(new String(buffer, 0, len)); s.close(); ``` 该代码实现了客户端与服务器的连接,并发送了一条文本消息,同时接收服务器的响应[^1]。 #### 服务端实现 服务端通过 `ServerSocket` 监听指定端口,等待客户端连接。一旦连接建立,服务端通过输入流接收客户端发送的数据,并通过输出流向客户端发送响应。例如: ```java ServerSocket ss = new ServerSocket(10012); Socket s = ss.accept(); InputStream in = s.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println(new String(buffer, 0, len)); PrintWriter out = new PrintWriter(s.getOutputStream(), true); out.println("<font color='red' size=7>客户端s你好</font>"); s.close(); ss.close(); ``` 该代码展示了如何在服务端接收客户端发送的数据,并向客户端发送 HTML 格式的响应[^3]。 #### TCP连接的建立与释放 TCP 连接的建立采用三次握手(Three-way Handshake): 1. 客户端发送 SYN(同步)报文给服务器,表示请求建立连接。 2. 服务器收到 SYN 报文后,发送 SYN-ACK(同步-确认)报文作为响应。 3. 客户端收到 SYN-ACK 后,发送 ACK(确认)报文,连接建立。 连接的释放采用四次挥手(Four-way Handshake): 1. 客户端发送 FIN(结束)报文,表示数据发送完成。 2. 服务器发送 ACK 报文,确认收到 FIN。 3. 服务器发送 FIN 报文,表示数据发送完成。 4. 客户端发送 ACK 报文,连接关闭。 #### TCP的可靠性机制 TCP 通过以下机制确保数据的可靠传输: - **确认机制**:接收方收到数据后,向发送方发送确认信息。 - **重传机制**:如果发送方未收到确认信息,则重传数据。 - **流量控制**:通过滑动窗口机制,控制发送速率,避免接收方缓冲区溢出。 - **拥塞控制**:通过慢启动、拥塞避免等算法,防止网络拥塞。 #### TCP的编程模型 TCP 编程模型通常包括以下几个步骤: 1. **创建 Socket**:客户端创建 `Socket` 对象,连接服务器;服务端创建 `ServerSocket` 对象,监听端口。 2. **获取流对象**:获取 `Socket` 的输入流和输出流,用于数据传输。 3. **数据读写**:通过输入流读取数据,通过输出流写入数据。 4. **关闭连接**:通信结束后,关闭 `Socket` 和流对象。 ### 示例代码:完整的 TCP 通信 以下是一个完整的 TCP 通信示例,包含客户端和服务端的代码。 #### 客户端代码 ```java import java.io.*; import java.net.*; public class TcpClient { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 8888); OutputStream out = socket.getOutputStream(); out.write("Hello Server!".getBytes()); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Server response: " + new String(buffer, 0, len)); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 服务端代码 ```java import java.io.*; import java.net.*; public class TcpServer { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server is listening on port 8888..."); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Client message: " + new String(buffer, 0, len)); OutputStream out = socket.getOutputStream(); out.write("Hello Client!".getBytes()); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值