疯狂Java讲义_Chapter17网络编程:(1)网络编程基础知识

本文介绍了Java中的网络编程基础知识,包括通信协议的组成、TCP/IP模型、IP地址与端口号的概念,以及Java中对网络支持的类如InetAddress、URLDecoder、URLEncoder和URLConnection的应用。通过示例展示了如何使用这些类进行网络操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.网络基础知识

  • 通信协议的三大组成部分:
    • 语义部分:决定双方对话的类型;
    • 语法部分:决定双方对话的格式;
    • 变换规则:决定通信双方的应答关系;
  • 国际标准化组织ISO在1978年提出开放互联参考模型OSI;
  • TCP/IP模型替代了OSI模型,TCP/IP模型包括:应用层、传输层、网络层、物理+数据链路层;

2.IP地址和端口号

  • IP地址用于唯一标识网络中的一个通信实体(主机、路由器端口);
  • IP地址是32位数字,为了方便记忆,将其用二进制分为4个部分,再转换为十进制:192.168.1.1;
  • 全球IP地址由NIC负责统一规划,APNIC负责亚太地区的IP管理;
  • 一个通信实体可能有多个通信程序进行,为了区分通信程序,设置了端口,每一个端口执行不同的通信程序;
    • 公认端口:绑定特定服务,0-1023;
    • 注册端口:应用程序的普遍选择,1024-49151;
    • 动态或私有端口:应用程序使用的动态端口,一般不会主动使用这些端口,49152-65535;

3.Java网络基本支持

1.使用InetAddress类

  • InetAddress类可以代表IP地址,Inet4Address和Inet6Address分别代表IPV4和IPV6;
  • InetAddress的基本用法(Page783)
  • 程序演示:

import java.net.*;

public class InetAddressTest
{
	public static void main(String[] args)
		throws Exception
	{
		//根据域名获得网站IP地址;
		InetAddress ip = InetAddress.getByName("www.crazyit.org");
		//判断网站能否访问
		System.out.println("网站是否可以访问?" + ip.isReachable(2000));
		//输出IP字符串
		System.out.println(ip.getHostAddress());
		//根据原始的IP地址获取对应的InetAddress实例
		InetAddress local = InetAddress.getByAddress(
			new byte[] {127, 0, 0, 1});
		System.out.println("判断本机是否可达" + local.isReachable(5000));
		//获取此IP地址对应的域名;
		System.out.println(local.getCanonicalHostName());
	}
}

2.使用URLDecoder和URLEncoder类

  • URLDecoder负责普通字符串的转换工作;
  • URLEncoder负责application/x-www-form-urlencoded MIME字符串(非西欧字符)的转换工作;
  • URLDecoder的decode方法将application/x-www-form-urlencoded MIME字符串转换成普通字符串;
  • URLEncoder的encode方法将普通字符串转换为application/x-www-form-urlencoded MIME字符串;
  • 演示方法:

import java.net.*;

public class URLDecoderTest
{
	public static void main(String[] args)
		throws Exception
	{
		// 将application/x-www-form-urlencoded字符串转换成普通字符串
		String keyWord = URLDecoder.decode(
			"%E7%96%AF%E7%8B%82java", "utf-8");
		System.out.println(keyWord);
		//将普通字符串转换为application/x-www-form-urlencoded字符串
		String urlStr = URLEncoder.encode(
			"疯狂讲义", "GBK");
		System.out.println(urlStr);
	}
}

3.URL、URLConnection和URLPermission

  1. URL类
  • URL类用于创建URL对象,URL对象代表了一种统一资源定位器,它是指向互联网资源的“指针”;URL由协议名、主机、端口号和资源组成;
  • URL类的方法(page785)
  • 程序演示:

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.*;

public class DownUtil
{
	//定义下载资源的路径;
	private String path;
	//定义下载文件的保存路径
    private String targetFile;
	//定义需要的线程数量
	private int threadNum;
	//定义下载的线程对象;
	private DownThread[] threads;
	//定义下载的文件总大小;
	private int fileSize;
    //初始化DownUtil类
	public DownUtil(String path, String targetFile, int threadNum)
	{
		this.path = path;
		this.threadNum = threadNum;
		//初始化threads数组
		threads = new DownThread[threadNum];
		this.targetFile = targetFile;
	}

	public void download() throws Exception
	{
		var url = new URL(path);    //获得URL对象
		var conn = (HttpURLConnection) url.openConnection();    //返回一个与URL所引用的远程对象的连接;
		conn.setConnectTimeout(5 * 1000);   
		conn.setRequestMethod("GET");
		conn.setRequestProperty(
			"Accept",
			"image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
			+ "application/x-shockwave-flash, application/xaml+xml, "
			+ "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
			+ "application/x-ms-application, application/vnd.ms-excel, "
			+ "application/vnd.ms-powerpoint, application/msword, */*");
		conn.setRequestProperty("Accept-Language", "zh-CN");
		conn.setRequestProperty("Charset", "UTF-8");
		conn.setRequestProperty("Connection", "Keep-Alive");
		//得到文件大小
		fileSize = conn.getContentLength();
		conn.disconnect();
		
		int currentPartSize = fileSize / threadNum + 1;
		var file = new RandomAccessFile(targetFile, "rw");
		//设置本地文件大小
		file.setLength(fileSize);
		file.close();
		for (var i = 0; i < threadNum; i++)
		{
			//计算每个线程开始下载的位置
			var startPos = i * currentPartSize;
			//每个线程使用一个RAF进行下载
			var currentPart = new RandomAccessFile(targetFile, "rw");
			//定义该线程的下载位置
			currentPart.seek(startPos);
			//创建下载线程
			threads[i] = new DownThread(startPos, currentPartSize, currentPart);
			// 启动下载线程
			threads[i].start();
		}
	}

	// 获取下载的完成百分比
	public double getCompleteRate()
	{
		// 统计多个线程已经下载的总大小
		var sumSize = 0;
		for (var i = 0; i < threadNum; i++)
		{
			sumSize += threads[i].length;
		}
		//返回完成百分比
		return sumSize * 1.0 / fileSize;
	}

	private class DownThread extends Thread
	{
		// 当前线程的下载位置
		private int startPos;
		// 定义当前线程负责下载的文件大小
		private int currentPartSize;
		// 当前线程需要下载的文件块
		private RandomAccessFile currentPart;
		// 定义当前线程已下载的字节数
		public int length;

		public DownThread(int startPos, int currentPartSize,
			RandomAccessFile currentPart)
		{
			this.startPos = startPos;
			this.currentPartSize = currentPartSize;
			this.currentPart = currentPart;
		}

		@Override
		public void run()
		{
			try
			{
				var url = new URL(path);
				var conn = (HttpURLConnection) url.openConnection();
				conn.setConnectTimeout(5 * 1000);
				conn.setRequestMethod("GET");
				conn.setRequestProperty(
					"Accept",
					"image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
					+ "application/x-shockwave-flash, application/xaml+xml, "
					+ "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
					+ "application/x-ms-application, application/vnd.ms-excel, "
					+ "application/vnd.ms-powerpoint, application/msword, */*");
				conn.setRequestProperty("Accept-Language", "zh-CN");
				conn.setRequestProperty("Charset", "UTF-8");
				InputStream inStream = conn.getInputStream();
				inStream.skip(this.startPos);
				var buffer = new byte[1024];
				var hasRead = 0;
				while (length < currentPartSize
					&& (hasRead = inStream.read(buffer)) != -1)
				{
					currentPart.write(buffer, 0, hasRead);
					length += hasRead;
				}
				currentPart.close();
				inStream.close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}
}

2.URLConnection对象表示应用程序和URL之间的通信连接,程序可以通过URLConnection实现向该URL发送请求、读取URL引用的资源;HTTPURLConnection对象表示应用程序与URL的HTTP连接;

3.URLPermission对象负责管理URLConnection对象的权限问题;

  • 创建一个和URL的连接,并发送请求,读取URL资源需要如下几个步骤:
    1. 通过调用URL对象的openConnection()方法来创建URLConnection对象;
    2. 设置URLConnection的参数和普通请求属性;
    3. 如果只是发送GET方式请求,则使用connect()方法建立和远程资源之间的实际连接;如果需要发送POST方式的请求,则需要获取URLConnection示例对应的输出流来发送请求参数
    4. 远程资源变为可用,程序可以访问远程资源的头字段或通过输入流读取远程资源的数据;
  • 程序演示:

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

public class GetTest
{
	public static String sendGet(String url, String param)
	{
		String result = "";
		String urlName = url + "?" + param;
		try
		{
			var realUrl = new URL(urlName);
			//创建和URL的连接对象
			URLConnection conn = realUrl.openConnection();
			//设置连接参数
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
				"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
			//启动连接
			conn.connect();
			// 获取所有响应的头字段
			Map<String, List<String>> map = conn.getHeaderFields();
			// 遍历响应头字段
			for (var key : map.keySet())
			{
				System.out.println(key + "--->" + map.get(key));
			}
			try (
				//定义BufferedReader来读取URL响应
				var in = new BufferedReader(
					new InputStreamReader(conn.getInputStream(), "utf-8")))
			{
				String line;
				while ((line = in.readLine())!= null)
				{
					result += "\n" + line;
				}
			}
		}
		catch (Exception e)
		{
			System.out.println("发送GET请求出现异常" + e);
			e.printStackTrace();
		}
		return result;
	}

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值