Java网络编程(二)-基于http协议的网络编程

本篇博客介绍另一种编程方式-基于http协议的网络编程,实现不同主机之间的通信。下面从HTTP、URL、URLConnection给出基于http协议的网络编程。

1、URL
URI:统一资源标识符,采用一种特定语法标识资源的字符串。通用的URI会告诉你资源是什么,是抽象的。

URL也是一种URI,但其除了标识一个资源,还会为资源提供一个特定的网络位置。和URI不同的是,URL会告诉你资源在哪里以及如何得到这个资源,是具体的。

URL类是Java程序在网络上定位和获取数据最简单的方法,我们无需关注所底层所使用的协议的细节,也不需要担心如何与服务器通信。只要把创建一个URL类的实例,就可以获得服务端的数据。下面看一个具体的示例:

package com.wygu.url;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class URLNetCommunicate {

    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            URL url = new URL("http://www.baidu.com/");
            //利用方法openStream()获取URL的输入流
            reader = new BufferedReader(new InputStreamReader(url.openStream()));
            String readStr = null;
            while((readStr=reader.readLine())!=null){
                System.out.println(new String(readStr.getBytes(),"UTF-8"));
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null!=reader){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在上面的示例中,首先创建一个URL的实例,然后利用方法openStream()打开输入流获取输入流BufferedReader对象reader,从reader中读取数据从而得到url所指定的资源文件。 对于所使用的openStream()方法只能读取服务端的数据,而不能发送数据。而如果既要读取数据又要发送数据,可以利用URL类的方法openConnection()创建一个URLConnection类的实例。本篇博客会在下面详细介绍。

2、HTTP
HTTP(超文本传输协议)是Web浏览器和Web服务器之间通信的标准协议。HTTP制定客户端与服务器如何建立连接、客户端如何从服务器请求数据,服务器如何响应请求,以及最后如何关闭连接。HTTP连接采用TCP/IP协议传输数据。
(1)HTTP协议解析
1)HTTP协议版本
HTTP/1.0:一个TCP连接只能发送一个Web请求;HTTP /1.0会为每个请求打开一个新的链接,使用完成后就关闭连接。
HTTP/1.1及以后版本:一个TCP连接可以连续发送对个请求和应答,此外请求和应答可以分为多个块发送;HTTP/1.1中,服务器不必在发送响应后就关闭连接,可以保持连接打开,在同一个socket上等待来自客户端的新请求。通过connection:Keep-Alive实现。
2)HTTP协议报文的请求和应答
在HTTP协议中,每个请求和响应都有同样的基本形式:一个首部行,一个包含元数据的HTTP首部,一个空行,然后是一个消息体:
Post请求

POST http://127.0.0.1:8080/cloud-pos-payment/TransServlet

POST data:
transType=CPU007

Request Headers:
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded;charset=utf-8
Content-Length: 1357
Host: 127.0.0.1:8080
User-Agent: Apache-HttpClient/4.2.6 (java 1.5)

可以看到请求头中字段都是以键-值对的形式出现。

2)HTTP方法
HTTP中主要有4个方法:GET,POST,PUT,DELETE。这四个方法均有特定的语义,应用程序必须遵循这些语义。下面主要介绍两种比较常见的方法:GET、POST。
GET方法:获取一个资源的表示,可以重复执行,输出会有缓存。GET请求在URL中会包括所有的必要信息,可以对GET请求加书签,或者进行链接和搜索,主要应用与非提交的动作。此外GET请求会把报文放在报文头中,因而其是可见的。
POST方法:将资源的一个表示上传到已知URL的服务器中。POST用于不能重复的不安全的操作。POST主要用于提交某个东西的动作。此外POST请求会把报文放在报文体中,因而其是不可见的。

例如:在购物车中增加一个商品应当发送一个GET请求,下订单时就应当发送一个POST请求。

3、URLConnection/HttpURLConnection
URLConnection是一个抽象类,和URL类相比(1)它对与HTTP服务器的交互提供了更多的控制;(2)它可以使用HTTP的请求方法POST、GET等向服务器发送数据。
直接使用URLConnection类的程序遵循以下步骤:
(1)构造一个URL实例;
(2)调用URL实例的方法openConnection()获得URLConnection实例;
(3)个性化配置URLConnection实例;
(4)获得输入流并读取数据;
(5)获得输出流并写入数据;
(7)关闭连接。
下面按照上述步骤,给出一个具体的服务端和客户端事例。
利用HttpServlet创建服务端:

package com.wygu.http;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServerServlet extends HttpServlet{

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException { 
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        System.out.println("收到来自客户端的请求报文.......");
        //设置请求的编码格式
        request.setCharacterEncoding("UTF-8");
        //获得HTTP请求参数中的内容
        String userName = request.getParameter("username");
        String userPwd = request.getParameter("passward");
        String strResponse ="";
        if("wygu".equals(userName)&&"0123456".equals(userPwd)){
            strResponse = "{" +
                "respCode:'"+ "00" +"'," +
                "respText:'Success'" +
                "}";
        }else{
            strResponse = "{" +
                    "respCode:'"+ "01" +"'," +
                    "respText:'Fail'" +
                    "}";
        }
        System.out.println("发送客户端的应答报文为:"+strResponse);
        //向response返回应答报文
        PrintWriter out = response.getWriter();
        out.print(strResponse);
        //刷新缓冲流,使其立即发送
        out.flush();
        out.close();           
    }
}

服务端在web.xml中配置ServerServlet 映射关系:

    <servlet>  
        <servlet-name>ServerServlet</servlet-name>  
        <servlet-class>com.wygu.http.ServerServlet</servlet-class>  
    </servlet>  

    <servlet-mapping>  
        <servlet-name>ServerServlet</servlet-name>  
        <url-pattern>/ServerServlet</url-pattern>  
    </servlet-mapping>  

客户端创建HTTP连接,并通过GET方法或者POST方法发送数据到服务端:

package com.wygu.http;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

public class Client {

    //实现Map型数据转换为key1=value1&key2=value2的类型
    public static String converMap2KeyValue(HashMap<String, String> map){
        if(null==map || map.size()<1){
            return "";
        }
        Iterator<Entry<String, String>> it= map.entrySet().iterator();
        StringBuffer sf = new StringBuffer();
        while (it.hasNext()) {
            Entry<String, String> en = it.next();
            sf.append(en.getKey() + "=" + en.getValue()
                    + "&");
        }
        return sf.substring(0, sf.length() - 1);
    }

    public static void main(String[] args) {
        HttpURLConnection httpURLConnection = null;
        URL url = null;
        PrintWriter writer = null;
        BufferedReader reader = null;
        try {
            url = new URL("http://localhost:8080/http-communication/"+"ServerServlet");     //创建本地URL
            httpURLConnection = (HttpURLConnection) url.openConnection();   //生成HttpURLConnection连接
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        httpURLConnection.setConnectTimeout(3000);// 连接超时时间,单位为毫秒
        httpURLConnection.setReadTimeout(3000);// 读取结果超时时间,单位为毫秒
        httpURLConnection.setDoInput(true); // 可读
        httpURLConnection.setDoOutput(true); // 可写
        httpURLConnection.setUseCaches(false);// 取消缓存
        httpURLConnection.setRequestProperty("Content-type",
                "application/x-www-form-urlencoded;charset=" + "utf-8");
        try {
            //httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Connection", "Keep-Alive");           // 设置维持长连接
            writer =new PrintWriter(new BufferedOutputStream(httpURLConnection.getOutputStream()));//获得HTTP连接的输出流
            HashMap<String,String> reqMap = new HashMap<String,String>();
            reqMap.put("username", "wygu");
            reqMap.put("passward", "0123456");
            writer.write(converMap2KeyValue(reqMap)); 
            writer.flush();
            int responseCode=httpURLConnection.getResponseCode();   
            if(responseCode==HttpURLConnection.HTTP_OK){//表示请求成功 
                reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));//获得HTTP连接的输入流
                String readStr = null;
                while((readStr=reader.readLine())!=null){
                    System.out.println(new String(readStr.getBytes(),"UTF-8"));
                }
            }else{
                System.out.println("HTTP响应失败,响应码为:"+responseCode);
            }   
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(null!=writer){
                    writer.close();
                }
                if(null!=reader){
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

运行后,服务端输出结果为:
收到来自客户端的请求报文…….
发送客户端的应答报文为:{respCode:’00’,respText:’Success’}

客户端输出结果为:
{respCode:’00’,respText:’Success’}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值