黑马程序员---URL

这篇博客探讨了在ASP.Net+Unity开发背景下,URL和URI在.NET及Java中的应用。作者通过对比IE浏览器与普通接收数据的方式,解释了URL在传输层和应用层的角色。文章介绍了Java中的URL类,指出URL对象提供了方便的操作方法,并讲解了如何使用URLConnection进行应用层的数据获取。
摘要由CSDN通过智能技术生成

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

 

为什么人家IE浏览器访问就没有响应头呢?因为我们用的是传输层协议,我们就获取到了服务器给我们发过来的所有数据,并把数据展示到了文本区域当中。

而浏览器它做了什么事情呢?它对这些消息进行了解析,把符合应用层协议的消息解析完拆包去掉了,把正确的正文数据主体部分显示到了自己接收的区域范围内。

我们在访问之前呢,对URL进行了解析,将IP地址和端口号都解析出来之后呢,我们封装了Socket对象,进行了接收数据。但我们知道URL是一个麻烦的东西,其实API帮我们封装好了URL对象,提供了许多操作方法。下面我们来学习一下URL类。

 URI比URL范围大

java.net
类 URL

构造方法摘要
URL(String spec) 使用URL地址来封装对象
          根据 String 表示形式创建 URL 对象。
URL(String protocol,String host, int port,String file) (协议、主机、端口、文件)
          根据指定 protocolhostport 号和 file 创建 URL 对象。
URL(String protocol,String host, int port,String file,URLStreamHandler handler)
          根据指定的 protocolhostport 号、filehandler 创建URL 对象。
URL(String protocol,String host,String file)
          根据指定的 protocol 名称、host 名称和 file 名称创建 URL。
URL(URL context,String spec)
          通过在指定的上下文中对给定的 spec 进行解析创建 URL。
URL(URL context,String spec,URLStreamHandler handler)
          通过在指定的上下文中用指定的处理程序对给定的 spec 进行解析来创建 URL。

方法摘要
 booleanequals(Object obj)
          比较此 URL 是否等于另一个对象。

以下方法以这个URL地址为例:http://192.168.1.100:8080/myweb/demo.html?tn=99914124_hao_pg

 StringgetFile()
          获取此 URL 的文件名。/myweb/demo.html?tn=99914124_hao_pg
 StringgetHost()
          获取此 URL 的主机名(如果适用)。192.168.1.100
 StringgetPath()
          获取此 URL 的路径部分。/myweb/demo.html
 intgetPort() 当你没有指定端口号的时候,返回-1。如果这个端口号返回-1,我们默认将端口号设置为80。
          获取此 URL 的端口号。8080
 StringgetProtocol()
          获取此 URL 的协议名称。http
 StringgetQuery() 
          获取此 URL 的查询部分。tn=99914124_hao_pg

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

class MyIEFrame 
{
	private Frame f;
	private Button b;
	private TextField tf;
	private TextArea ta;

	private Dialog d;
	private Button okButton;
	private Label label;
	
	MyIEFrame()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my IE");
		tf = new TextField(70);
		b = new Button("转到");
		ta = new TextArea(32,78);

		f.setBounds(300,150,600,580);
		f.setLayout(new FlowLayout());

		f.add(tf);
		f.add(b);
		f.add(ta);

		d = new Dialog(f,"文件资源管理器",true);
		okButton = new Button("确定");
		label = new Label();

		d.setLayout(new FlowLayout());

		d.add(label);
		d.add(okButton);

		myEvent();

		f.setVisible(true);
	}

	public void myEvent()
	{
		//点击“关闭”按钮关闭对话框。
		d.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				d.setVisible(false);
			}
		});

		//点击“确定”按钮关闭对话框。
		okButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				d.setVisible(false);
			}
		});

		//敲“回车”获取文件列表内容。
		tf.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				if(e.getKeyCode()==e.VK_ENTER)
				{
					getList();
				}
			}
		});
		
		//点"转到"获取文件列表内容。
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				getList();
			}
		});
	
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
	}

	private void getList()
	{
		ta.setText(null);

		/*
		//解析地址栏的网址
		//http://192.168.1.100:8080/myweb/demo.html
		String url = tf.getText();
		//int indexOf(String str)返回指定字符串在此字符串中第一次出现处的索引。
		int index1 = url.indexOf("//");
		//indexOf(String str, int fromIndex)
		int index2 = url.indexOf("/",index1+2);
		
		//substring(int beginIndex, int endIndex) 
		String substr = url.substring(index1+2,index2);
		
		//split(String regex)
		String[] arr = substr.split(":");
		String hostAddress = arr[0];
		int port = Integer.parseInt(arr[1]);
		*/

		try
		{
			//使用URL对象,解析地址栏的网址。
			String url = tf.getText();
			URL u = new URL(url);
			String hostAddress = u.getHost();
			int port = u.getPort(); 


			//建立浏览器的客户端Socket服务
			Socket s = new Socket(hostAddress,port);

			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			
			//向服务端发送HTTP请求消息头:
			out.println("GET /myweb/demo.html HTTP/1.1");
			out.println("Accept: */*");
			out.println("Accept-Language: zh-cn");
			out.println("Host: 192.168.1.100:8080");
			out.println("Connection: closed");
			
			//这里一定要记得写上空行分隔符,否则服务器不识别
			out.println();
			out.println();

			//接收服务端信息:
			InputStream in = s.getInputStream();
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=in.read(buf))!=-1)
			{
				String info = new String(buf,0,len);
				ta.append(info);
			}

			s.close();
		}
		catch (Exception ex)
		{
		}
	}

	public static void main(String[] args) 
	{
		new MyIEFrame();
	}
}


 调用以下方法,由传输层转向应用层:

URLConnectionopenConnection()
          返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

class MyIEFrame 
{
	private Frame f;
	private Button b;
	private TextField tf;
	private TextArea ta;

	private Dialog d;
	private Button okButton;
	private Label label;
	
	MyIEFrame()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my IE");
		tf = new TextField(70);
		b = new Button("转到");
		ta = new TextArea(32,78);

		f.setBounds(300,150,600,580);
		f.setLayout(new FlowLayout());

		f.add(tf);
		f.add(b);
		f.add(ta);

		d = new Dialog(f,"文件资源管理器",true);
		okButton = new Button("确定");
		label = new Label();

		d.setLayout(new FlowLayout());

		d.add(label);
		d.add(okButton);

		myEvent();

		f.setVisible(true);
	}

	public void myEvent()
	{
		//点击“关闭”按钮关闭对话框。
		d.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				d.setVisible(false);
			}
		});

		//点击“确定”按钮关闭对话框。
		okButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				d.setVisible(false);
			}
		});

		//敲“回车”获取文件列表内容。
		tf.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				if(e.getKeyCode()==e.VK_ENTER)
				{
					getList();
				}
			}
		});
		
		//点"转到"获取文件列表内容。
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				getList();
			}
		});
	
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
	}

	private void getList()
	{
		ta.setText(null);

		/*
		//解析地址栏的网址
		//http://192.168.1.100:8080/myweb/demo.html
		String url = tf.getText();
		//int indexOf(String str)返回指定字符串在此字符串中第一次出现处的索引。
		int index1 = url.indexOf("//");
		//indexOf(String str, int fromIndex)
		int index2 = url.indexOf("/",index1+2);
		
		//substring(int beginIndex, int endIndex) 
		String substr = url.substring(index1+2,index2);
		
		//split(String regex)
		String[] arr = substr.split(":");
		String hostAddress = arr[0];
		int port = Integer.parseInt(arr[1]);
		*/

		try
		{
			//使用URL对象,解析地址栏的网址。
			String url = tf.getText();
			URL u = new URL(url);
			String hostAddress = u.getHost();
			int port = u.getPort(); 
			if(port==-1)
			{
				port = 80;
			}

			URLConnection uc = u.openConnection();
			ta.setText(uc.toString());


/*
			//建立浏览器的客户端Socket服务
			Socket s = new Socket(hostAddress,port);

			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			
			//向服务端发送HTTP请求消息头:
			out.println("GET /myweb/demo.html HTTP/1.1");  */
//			out.println("Accept: */*");
/*			out.println("Accept-Language: zh-cn");
			out.println("Host: 192.168.1.100:8080");
			out.println("Connection: closed");
			
			//这里一定要记得写上空行分隔符,否则服务器不识别
			out.println();
			out.println();

			//接收服务端信息:
			InputStream in = s.getInputStream();
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=in.read(buf))!=-1)
			{
				String info = new String(buf,0,len);
				ta.append(info);
			}

			s.close();
*/
		}
		catch (Exception ex)
		{
		}
	}

	public static void main(String[] args) 
	{
		new MyIEFrame();
	}
}

已经在应用层建立了连接,既然已经建立连接,我们是不是要获取数据啊: 

java.net
URLConnection

直接已知子类:
HttpURLConnection, JarURLConnection

public abstract class URLConnection
extends Object
构造方法摘要
protected URLConnection(URL url)
          构造一个到指定 URL 的 URL 连接。

方法摘要
  InputStreamgetInputStream() 此类封装了一个Socket对象,将Socket对象的输入流给你。
          返回从此打开的连接读取的输入流。
abstract  voidconnect()
          打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。
  OutputStreamgetOutputStream()
          返回写入到此连接的输出流。

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

class MyIEFrame 
{
	private Frame f;
	private Button b;
	private TextField tf;
	private TextArea ta;

	private Dialog d;
	private Button okButton;
	private Label label;
	
	MyIEFrame()
	{
		init();
	}

	public void init()
	{
		f = new Frame("my IE");
		tf = new TextField(70);
		b = new Button("转到");
		ta = new TextArea(32,78);

		f.setBounds(300,150,600,580);
		f.setLayout(new FlowLayout());

		f.add(tf);
		f.add(b);
		f.add(ta);

		d = new Dialog(f,"文件资源管理器",true);
		okButton = new Button("确定");
		label = new Label();

		d.setLayout(new FlowLayout());

		d.add(label);
		d.add(okButton);

		myEvent();

		f.setVisible(true);
	}

	public void myEvent()
	{
		//点击“关闭”按钮关闭对话框。
		d.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				d.setVisible(false);
			}
		});

		//点击“确定”按钮关闭对话框。
		okButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				d.setVisible(false);
			}
		});

		//敲“回车”获取文件列表内容。
		tf.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				if(e.getKeyCode()==e.VK_ENTER)
				{
					getList();
				}
			}
		});
		
		//点"转到"获取文件列表内容。
		b.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				getList();
			}
		});
	
		//点击“关闭”按钮关闭frame窗体。
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});
	}

	private void getList()
	{
		ta.setText(null);

		/*
		//解析地址栏的网址
		//http://192.168.1.100:8080/myweb/demo.html
		String url = tf.getText();
		//int indexOf(String str)返回指定字符串在此字符串中第一次出现处的索引。
		int index1 = url.indexOf("//");
		//indexOf(String str, int fromIndex)
		int index2 = url.indexOf("/",index1+2);
		
		//substring(int beginIndex, int endIndex) 
		String substr = url.substring(index1+2,index2);
		
		//split(String regex)
		String[] arr = substr.split(":");
		String hostAddress = arr[0];
		int port = Integer.parseInt(arr[1]);
		*/

		try
		{
			//使用URL对象,帮我们解析地址栏的网址,再也不用对地址切来切去的了。
			String url = tf.getText();
			URL u = new URL(url);
			String hostAddress = u.getHost();
			int port = u.getPort(); 
			if(port==-1)
			{
				port = 80;
			}
			
			//使用URLConnection对象,替我们发出了请求消息头,建立了Socket对象,连接到了服务器。
			URLConnection uc = u.openConnection();
			//ta.setText(uc.toString());

			//获取网络输入流,接收服务端的数据。
			InputStream in = uc.getInputStream();
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=in.read(buf))!=-1)
			{
				ta.append(new String(buf,0,len));
			}


/*
			//建立浏览器的客户端Socket服务
			Socket s = new Socket(hostAddress,port);

			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			
			//向服务端发送HTTP请求消息头:
			out.println("GET /myweb/demo.html HTTP/1.1");  */
//			out.println("Accept: */*");
/*			out.println("Accept-Language: zh-cn");
			out.println("Host: 192.168.1.100:8080");
			out.println("Connection: closed");
			
			//这里一定要记得写上空行分隔符,否则服务器不识别
			out.println();
			out.println();

			//接收服务端信息:
			InputStream in = s.getInputStream();
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=in.read(buf))!=-1)
			{
				String info = new String(buf,0,len);
				ta.append(info);
			}

			s.close();
*/
		}
		catch (Exception ex)
		{
		}
	}

	public static void main(String[] args) 
	{
		new MyIEFrame();
	}
}


我们发现响应消息头去掉了

甚至可以打开hao123网址,只是不能识别而已。

 

小知识点

Socket类(客户端套接字)中 有一个空参构造函数:

构造方法摘要
 Socket()
          通过系统默认类型的 SocketImpl 创建未连接套接字

方法摘要
 
 
voidconnect(SocketAddress endpoint)
          将此套接字连接到服务器。

 可用此方法与服务端建立连接,我们来看一下参数SocketAddress:

public abstract class SocketAddress

是一个抽象类,来看它的直接已知子类 InetSocketAddress:

public class InetSocketAddress  extends SocketAddress 

此类实现 IP 套接字地址(IP 地址 + 端口号)。它还可以是一个对(主机名 + 端口号),

InetAddress是(IP地址),SocketAddress是(IP 地址 + 端口号)。

 

ServerSocket类(服务端套接字)有一个构造方法:

构造方法摘要
 
ServerSocket(int port)
          创建绑定到特定端口的服务器套接字。
ServerSocket(int port, int backlog)
          利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。

 int 型的 backlog 是什么意思呢?

参数:
port - 指定的端口;或者为 0,表示使用任何空闲端口。
backlog - 队列的最大长度。(能连接到服务器的客户端的最大同时个数

 

网络知识

浏览器写入一个网址在访问一台主机的时候它到底做了什么事情?

http://192.168.1.100:8080/myweb/demo.html

首先浏览器在解析完这句话以后,它首先会看是什么协议(HTTP),它会去启动相对应的协议,

并解析后面的主机和端口,把主机和端口封装成Socket,

我们写的时候通常会写www.sina.com.cn ,

需要把主机名翻译成IP地址,才能去访问主机,到哪去翻译成IP地址呢?

想要将主机名翻译成IP地址,需要域名解析,这时候就需要一个DNS域名解析服务器,

浏览器先在本机的C:\Windows\System32\Drivers\etc\hosts文件中找,如果没找着,再去公网上找一台域名解析服务器,

这台服务器记录的是:sina 这个主机对应的IP地址。(主机名和IP地址的映射关系表)

公网的这个DNS里面记录的都是这些知名网站的主机名和IP地址映射关系。

 

 

 其实 127.0.0.1 和 localhost 的映射关系就在本机上,C:\Windows\System32\Drivers\etc\hosts

 这个东西还有一种应用,有些收费软件会不定期的到自己网站去升级,去验证你的这个注册码,如果发现你的这个注册码是伪注册码的话,就会给你发一些东西不让你用这个软件了,你在本地的hosts文件将这个软件的的主机名给它对应一个本地的IP地址,这个软件就不能更新了。

还有就是一些不好的网站老师网出弹,或者在你不经意间就不小心点住了,你也可以再hosts文件中给它映射到本地IP地址。

 

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值