---------------------- 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) (协议、主机、端口、文件) 根据指定 protocol 、host 、port 号和 file 创建 URL 对象。 | |
URL(String protocol,String host, int port,String file,URLStreamHandler handler) 根据指定的 protocol 、host 、port 号、file 和handler 创建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。 |
方法摘要 | |
---|---|
boolean | equals(Object obj) 比较此 URL 是否等于另一个对象。 |
以下方法以这个URL地址为例:http://192.168.1.100:8080/myweb/demo.html?tn=99914124_hao_pg
String | getFile() 获取此 URL 的文件名。/myweb/demo.html?tn=99914124_hao_pg |
String | getHost() 获取此 URL 的主机名(如果适用)。192.168.1.100 |
String | getPath() 获取此 URL 的路径部分。/myweb/demo.html |
int | getPort() 当你没有指定端口号的时候,返回-1。如果这个端口号返回-1,我们默认将端口号设置为80。 获取此 URL 的端口号。8080 |
String | getProtocol() 获取此 URL 的协议名称。http |
String | getQuery() 获取此 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();
}
}
调用以下方法,由传输层转向应用层:
URLConnection | openConnection() 返回一个 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
构造方法摘要 | |
---|---|
protected | URLConnection(URL url) 构造一个到指定 URL 的 URL 连接。 |
方法摘要 | |
---|---|
InputStream | getInputStream() 此类封装了一个Socket对象,将Socket对象的输入流给你。 |
abstract void | connect() 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。 |
OutputStream | getOutputStream() 返回写入到此连接的输出流。 |
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 创建未连接套接字 |
方法摘要 | |
---|---|
| |
| |
void | connect(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