0009 Java 与 Http 协议

来源:互联网 发布:ubuntu重启网络命令 编辑:程序博客网 时间:2024/05/17 22:44

       1 http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于 TCP 的连接方式。HTTP 协议的主要特点是:

     (1).支持客户/服务器模式。
     (2).简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于 HTTP 协议简单,通信速度很快。
     (3).灵活:HTTP 允许传输任意类型的数据对象。类型由 Content-Type 加以标记。
     (4).无连接:即每次连接只处理一个请求,处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
     (5).无状态:无状态是指协议对于事务处理没有记忆能力。 

     http1.0 协议默认的是非持久连接。 (非持久连接:每次服务器发出一个对象后,相应的 TCP 连接就被关闭,就是说每个连接都没有持续到可用于传送其他对象。每个 TCP 连接只用于传输一个请求消息和一个响应消息。)

     HTTP1.1 默认的连接方式为持久连接。(持久连接:服务器在发出响应后让 TCP 连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。HTTP/1.1 的默认模式使用带流水线的持久连接。)
     
     2、 如果要实现网络互联我们要思考两个需要解决的技术问题:
        第一:浏览器和服务器是通过什么来连接的。
        第二:这种连接方式是怎么实现的。
        通过 Internet 去发送到服务器当中,而 Internet 内部可以通过三种方式来实现发送信息和数据:
        (1) HTTP 协议,也是在工作中最常用的,是建立在 TCP/IP 基础上实现的。
        (2) FTP 协议
        (3) TCP/IP 协议,它也是最底层的协议,其它的方式必须是要通过它,但是要想实现这种协议必须要实现socket 编程,这种方法是用来上传一些比较大的文件,视频,进行断点续传的操作。

      3、 Http 实例剖析:


 下面是对以上流程的具体分析:

    第一步:在浏览器客户端中得到用户输入的内容。
    第二步:浏览器得到这个网址之后,内部会将这个域名发送到 DNS 上,进行域名解析。得到它的 IP 之后就会链接到指定的服务器上,假如服务器的地址是:221.104.13.32:80,从浏览器到服务器端口它使用到最底层的TCP/IP 协议。
    第三步:实现 TCP/IP 协议用 Socket 来完成,使用了 Socket 的套接字。
    第四步:服务器端的 80 端口监听客户端的链接,这样客户端到服务器就链接上了。

    4、HTTP 协议
        下面详细讲解一下 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 则没有此限制。
         (5) 安全性问题。正如 (2) 中提到,使用 GET 的时候,参数会显示在地址栏上,而 POST 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 GET;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 POST 为好。
    5、Java 中使用 HTTP
      下面通过两个例子来分别讲解一下 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>




0 0
原创粉丝点击