1、 http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于 TCP 的连接方式。HTTP 协议的主要特点是:
(1).支持客户/服务器模式。
(2).简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于 HTTP 协议简单,通信速度很快。
(3).灵活:HTTP 允许传输任意类型的数据对象。类型由 Content-Type 加以标记。
(4).无连接:即每次连接只处理一个请求,处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
(5).无状态:无状态是指协议对于事务处理没有记忆能力。
http1.0 协议默认的是非持久连接。 (非持久连接:每次服务器发出一个对象后,相应的 TCP 连接就被关闭,就是说每个连接都没有持续到可用于传送其他对象。每个 TCP 连接只用于传输一个请求消息和一个响应消息。)
第二:这种连接方式是怎么实现的。
(2) FTP 协议
(3) TCP/IP 协议,它也是最底层的协议,其它的方式必须是要通过它,但是要想实现这种协议必须要实现socket 编程,这种方法是用来上传一些比较大的文件,视频,进行断点续传的操作。
3、 Http 实例剖析:
第一步:在浏览器客户端中得到用户输入的内容。
第二步:浏览器得到这个网址之后,内部会将这个域名发送到 DNS 上,进行域名解析。得到它的 IP 之后就会链接到指定的服务器上,假如服务器的地址是:221.104.13.32:80,从浏览器到服务器端口它使用到最底层的TCP/IP 协议。
第三步:实现 TCP/IP 协议用 Socket 来完成,使用了 Socket 的套接字。
第四步:服务器端的 80 端口监听客户端的链接,这样客户端到服务器就链接上了。
下面详细讲解一下 HTTP 协议,因为 HTTP 是无状态的协议,所以服务端并不记录客户端之前发送信息,一码归一码,所以 HTTP 协议使用报文头的形式记录状态,一般分为请求报文和响应报文。一般用户使用浏览器访问网页,是无需关心 HTTP 请求的报文头,因为开发人员知道浏览器已经帮忙处理了,但是当进行开发工作的时候,这些是必须要了解的。
对于报文,一般关心请求方式,,是 GET 或者是 POST;请求数据类型,是文本还是音频;数据的编码格式,一般用 utf-8;发送的数据长度;响应返回码,一般 200 为成功,其他响应码都是有问题。
这里简单说一下 GET 方式和 POST 方式的差别:
(1) GET 是从服务器上获取数据,POST 是向服务器传送数据。
(2) 在客户端,GET 方式在通过 URL 提交数据,数据在 URL 中可以看到;POST 方式,数据放在 HTML HEADER 内提交。
(3) 对于 GET 方式,服务器端用 Request.QueryString 获取变量的值,对于 POST 方式,服务器用Request.Form 获取提交的数据。
(4) GET 方式提交的数据不能大于 2KB(主要是 URL 长度限制),而 POST 则没有此限制。
下面通过两个例子来分别讲解一下 GET 和 POST 在 Java 中的使用,如果在 Java 中需要使用 HTTP 协议进行访问,一般通过 HttpURLConnection 类来实现。
HttpURLConnection 继承了 URLConnection,所以在 URLConnection 的基础上进一步改进,增加了一些用于操作 HTTP 资源的便捷方法。Java 中 HttpURLConnection 对象通过 URL.openConnection() 方法来获得,需要进行强制转换。先来介绍几个 HttpURLConnection 的常用方法:
void setConnectTimeout(int timeout):设置连接超时时长,如果超过 timeout 时长,则放弃连接,单位以毫秒计算。
void setDoInput(boolean newValue) :标志是否允许输入。
void setDoOutput(boolean newValue):标志是否允许输出。
String getRequestMethod() : 获取发送请求的方法。
int getResponseCode() : 获取服务器的响应码。
void setRequestMethod(String method):设置发送请求的方法。
void setRequestProperty(String field,String newValue):设置请求报文头,并且只对当前的 HttpURLConnection 有效。
GET方式
这个例子通过 GET 方式从服务端获取一张图片的信息,并把其保存在本地磁盘中。服务器为本机上的 IIS,一张静态图片,直接通过 URL 访问。直接上 Java 代码,注释已经解释的很清楚了。
<span style="font-family:FangSong_GB2312;">package com.http.get;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class HttpUtils {
private static String URL_PATH = "http://192.168.1.106:8080/green.jpg";
/**
* @param args
*/
public static void main(String[] args) {
// 调用方法获取图片并保存
saveImageToDisk();
}
/**
* 通过 URL_PATH 的地址访问图片并保存到本地
*/
public static void saveImageToDisk()
{
InputStream inputStream= getInputStream();
byte[] data=new byte[1024];
int len=0;
FileOutputStream fileOutputStream=null;
try {
// 把图片文件保存在本地 F 盘下
fileOutputStream=new FileOutputStream("F:\\test.png");
while((len=inputStream.read(data))!=-1)
{
//向本地文件中写入图片流
fileOutputStream.write(data,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
finally
{
//最后关闭流
if(inputStream!=null)
{
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fileOutputStream!=null)
{
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 通过 URL 获取图片
* @return URL 地址图片的输入流。
*/
public static InputStream getInputStream() {
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try {
//根据 URL 地址实例化一个 URL 对象,用于创建 HttpURLConnection 对象。
URL url = new URL(URL_PATH);
if (url != null) {
// openConnection 获得当前 URL 的连接
httpURLConnection = (HttpURLConnection) url.openConnection();
//设置3秒的响应超时
httpURLConnection.setConnectTimeout(3000);
//设置允许输入
httpURLConnection.setDoInput(true);
//设置为 GET 方式请求数据
httpURLConnection.setRequestMethod("GET");
//获取连接响应码,200 为成功,如果为其他,均表示有问题
int responseCode=httpURLConnection.getResponseCode();
if(responseCode==200)
{
// getInputStream 获取服务端返回的数据流。
inputStream=httpURLConnection.getInputStream();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return inputStream;
}
}</span>
POST方式
这个例子通过 POST 方式访问一个登陆页面,需要输入用户名(username)和密码(password)。虽然这里使用的 Java 在讲解问题,但是服务端是使用 .Net 的框架,一个很简单的 HTML 页面加一个表单传送的一般处理程序,输入为 admin+123 为登陆成功,这里不累述了。
<pre name="code" class="java"><span style="font-family:FangSong_GB2312;font-size:18px;">package com.http.post;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
public class postUtils {
// 请求服务器端的url
private static String PATH = "http://192.168.222.1:1231/loginas.ashx";
private static URL url;
public postUtils() {
}
static {
try {
url = new URL(PATH);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过给定的请求参数和编码格式,获取服务器返回的数据
* @param params 请求参数
* @param encode 编码格式
* @return 获得的字符串
*/
public static String sendPostMessage(Map<String, String> params,
String encode) {
// 作为StringBuffer初始化的字符串
StringBuffer buffer = new StringBuffer();
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> entry : params.entrySet()) {
try {
// 完成转码操作
buffer.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(), encode))
.append("&"); //请求的参数之间使用&分割。
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
buffer.deleteCharAt(buffer.length() - 1);
System.out.println(buffer.toString());
try {
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setConnectTimeout(3000);
//设置 POST 方式请求数据
urlConnection.setRequestMethod("POST");
//设置允许输入输出
urlConnection.setDoInput(true);// 表示从服务器获取数据
urlConnection.setDoOutput(true);// 表示向服务器写数据
// 获得上传信息的字节大小以及长度
byte[] mydata = buffer.toString().getBytes();
//设置请求报文头,设定请求数据类型
urlConnection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
//设置请求数据长度
urlConnection.setRequestProperty("Content-Length",
String.valueOf(mydata.length));
// 获得输出流,向服务器输出数据
OutputStream outputStream = urlConnection.getOutputStream();
outputStream.write(mydata);
// 获得服务器响应的结果和状态码
int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) {
return changeInputStream(urlConnection.getInputStream(),
encode);
}
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
/**
* 把服务端返回的输入流转换成字符串格式
* @param inputStream 服务器返回的输入流
* @param encode 编码格式
* @return 解析后的字符串
*/
private static String changeInputStream(InputStream inputStream,
String encode) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int len = 0;
String result="";
if (inputStream != null) {
try {
while ((len = inputStream.read(data)) != -1) {
outputStream.write(data,0,len);
}
result=new String(outputStream.toByteArray(),encode);
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* @param args
*/
public static void main(String[] args) {
//通过Map设置请求字符串。
Map<String, String> params = new HashMap<String, String>();
params.put("username", "admin");
params.put("password", "123");
String result=sendPostMessage(params, "utf-8");
System.out.println(result);
}
}</span><span style="font-family:FangSong_GB2312;font-size:14px;">
</span>