Java基礎(chǔ):網(wǎng)絡(luò)編程

1. 網(wǎng)絡(luò)編程概述

1.1 計(jì)算機(jī)網(wǎng)絡(luò)

是指將地理位置不同的具有獨(dú)立功能的多臺計(jì)算機(jī)及其外部設(shè)備缩多,通過通信線路連接起來,在網(wǎng)絡(luò)操作系統(tǒng),網(wǎng)絡(luò)管理軟件及網(wǎng)絡(luò)通信協(xié)議的管理和協(xié)調(diào)下第献,實(shí)現(xiàn)資源共享和信息傳遞的計(jì)算機(jī)系統(tǒng)。

1.2 網(wǎng)絡(luò)編程

就是用來實(shí)現(xiàn)網(wǎng)絡(luò)互連的不同計(jì)算機(jī)上運(yùn)行的程序間可以進(jìn)行數(shù)據(jù)交換兔港。

1.3 網(wǎng)絡(luò)模型

計(jì)算機(jī)網(wǎng)絡(luò)之間以何種規(guī)則進(jìn)行通信庸毫,就是網(wǎng)絡(luò)模型研究問題。

網(wǎng)絡(luò)模型一般是指OSI(Open System Interconnection開放系統(tǒng)互連)參考模型或者TCP/IP參考模型衫樊。

應(yīng)用層:http飒赃、https、ftp科侈,傳輸層:TCP载佳、UDP,網(wǎng)絡(luò)層:IP臀栈,物理層蔫慧,數(shù)據(jù)鏈路層

網(wǎng)絡(luò)模型

1.4 網(wǎng)絡(luò)模型7層概述

  • 物理層

主要定義物理設(shè)備標(biāo)準(zhǔn),如網(wǎng)線的接口類型权薯、光纖的接口類型姑躲、各種傳輸介質(zhì)的傳輸速率等睡扬。它的主要作用是傳輸比特流(就是由1、0轉(zhuǎn)化為電流強(qiáng)弱來進(jìn)行傳輸,到達(dá)目的地后在轉(zhuǎn)化為1肋联、0威蕉,也就是我們常說的數(shù)模轉(zhuǎn)換與模數(shù)轉(zhuǎn)換)。這一層的數(shù)據(jù)叫做比特橄仍。

  • 數(shù)據(jù)鏈路層

主要將從物理層接收的數(shù)據(jù)進(jìn)行MAC地址(網(wǎng)卡的地址)的封裝與解封裝韧涨。常把這一層的數(shù)據(jù)叫做幀。在這一層工作的設(shè)備是交換機(jī)侮繁,數(shù)據(jù)通過交換機(jī)來傳輸虑粥。

  • 網(wǎng)絡(luò)層

主要將從下層接收到的數(shù)據(jù)進(jìn)行IP地址(例192.168.0.1)的封裝與解封裝。在這一層工作的設(shè)備是路由器宪哩,常把這一層的數(shù)據(jù)叫做數(shù)據(jù)包娩贷。

  • 傳輸層

定義了一些傳輸數(shù)據(jù)的協(xié)議和端口號(WWW端口80等),如:TCP(傳輸控制協(xié)議锁孟,傳輸效率低彬祖,可靠性強(qiáng),用于傳輸可靠性要求高品抽,數(shù)據(jù)量大的數(shù)據(jù))储笑,UDP(用戶數(shù)據(jù)報(bào)協(xié)議,與TCP特性恰恰相反圆恤,用于傳輸可靠性要求不高突倍,數(shù)據(jù)量小的數(shù)據(jù),如QQ聊天數(shù)據(jù)就是通過這種方式傳輸?shù)模?主要是將從下層接收的數(shù)據(jù)進(jìn)行分段和傳輸盆昙,到達(dá)目的地址后再進(jìn)行重組羽历。常常把這一層數(shù)據(jù)叫做段。

  • 會話層

通過傳輸層(端口號:傳輸端口與接收端口)建立數(shù)據(jù)傳輸?shù)耐返病V饕谀愕南到y(tǒng)之間發(fā)起會話或者接受會話請求(設(shè)備之間需要互相認(rèn)識可以是IP也可以是MAC或者是主機(jī)名)

  • 表示層

主要是進(jìn)行對接收的數(shù)據(jù)進(jìn)行解釋秕磷、加密與解密、壓縮與解壓縮等(也就是把計(jì)算機(jī)能夠識別的東西轉(zhuǎn)換成人能夠能識別的東西(如圖片炼团、聲音等)澎嚣。

  • 應(yīng)用層

主要是一些終端的應(yīng)用,比如說FTP(各種文件下載)们镜,WEB(IE瀏覽),QQ之類的(可以把它理解成我們在電腦屏幕上可以看到的東西.就是終端應(yīng)用)润歉。

PS:

  • 每個(gè)網(wǎng)卡的MAC地址都是全球唯一的模狭。
  • 路由器實(shí)現(xiàn)將數(shù)據(jù)包發(fā)送到指定的地點(diǎn)。
  • 應(yīng)用軟件之間通信的過程就是層與層之間封包踩衩、解封包的過程嚼鹉。
  • OSI參考模型雖然設(shè)計(jì)精細(xì)贩汉,但過于麻煩,效率不高锚赤,因此才產(chǎn)生了簡化版的TCP/IP參考模型匹舞。

1.5 封包、解封包的過程

封包线脚、解封包

2. 網(wǎng)絡(luò)編程三要素

網(wǎng)絡(luò)模型說完了,我們要進(jìn)行通訊,需要哪些要素呢?

比如說:我要跟你說話
第一個(gè)條件:我要先找到你 (IP)
第二個(gè)條件:你得有接收數(shù)據(jù)的地方赐稽,耳朵 (端口)
第三個(gè)條件:我跟你說話,你能接收到,咱按什么方式接收啊,我說英文你懂嗎,說韓文你懂嗎,不懂是吧,所以我還是說中文把(協(xié)議)

2.1 IP地址

網(wǎng)絡(luò)中計(jì)算機(jī)的唯一標(biāo)識,不易記憶浑侥,可用主機(jī)名姊舵。本地回環(huán)地址:127.0.0.1,主機(jī)名:localhost寓落。計(jì)算機(jī)只能識別二進(jìn)制的數(shù)據(jù)括丁,所以我們的IP地址應(yīng)該是一個(gè)二進(jìn)制的數(shù)據(jù)。為了方便表示IP地址伶选,我們就把IP地址的每一個(gè)字節(jié)上的數(shù)據(jù)換算成十進(jìn)制史飞,然后用.分開來表示:"點(diǎn)分十進(jìn)制"。

所謂IP地址就是給每個(gè)連接在Internet上的主機(jī)分配的一個(gè)32bit地址仰税。按照TCP/IP規(guī)定构资,IP地址用二進(jìn)制來表示,每個(gè)IP地址長32bit肖卧,比特?fù)Q算成字節(jié)蚯窥,就是4個(gè)字節(jié)。例如一個(gè)采用二進(jìn)制形式的IP地址是“00001010000000000000000000000001”塞帐,這么長的地址拦赠,人們處理起來也太費(fèi)勁了。為了方便人們的使用葵姥,IP地址經(jīng)常被寫成十進(jìn)制的形式涌庭,中間使用符號“.”分開不同的字節(jié)滞项。于是,上面的IP地址可以表示為“10.0.0.1”。IP地址的這種表示法叫做“點(diǎn)分十進(jìn)制表示法”忘闻,這顯然比1和0容易記憶得多。

通過ping 127.0.0.1可以測試網(wǎng)絡(luò)是不是通口芍,如果不通杖剪,可能是網(wǎng)卡出問題了

ip地址

通過ping命令還可以獲取到url對應(yīng)的IP地址,例如獲取網(wǎng)易新聞url(c.m.163.com)的IP地址

ping命令

查看本機(jī)IP地址ipconfig

ping命令

IP地址分類

IP地址的組成:IP地址 = 網(wǎng)絡(luò)號碼+主機(jī)地址

IPV4數(shù)量已經(jīng)不夠分配拨齐,所以產(chǎn)生了IPV6鳞陨。

ip

InetAddress類的使用

此類表示互聯(lián)網(wǎng)協(xié)議 (IP) 地址

返回值 方法 說明
InetAddress getByName(String host) 根據(jù)主機(jī)名或者IP地址的字符串表示得到IP地址對象
String getHostName() 獲取此 IP 地址的主機(jī)名
String getHostAddress() 返回 IP 地址字符串

代碼示例:

package cn.itcast_01;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        // public static InetAddress getByName(String host)
        // InetAddress address = InetAddress.getByName("liuyi");
        // InetAddress address = InetAddress.getByName("192.168.12.92");
        InetAddress address = InetAddress.getByName("192.168.12.63");

        // 獲取兩個(gè)東西:主機(jī)名,IP地址
        // public String getHostName()
        String name = address.getHostName();
        // public String getHostAddress()
        String ip = address.getHostAddress();
        System.out.println(name + "---" + ip);
    }
}

運(yùn)行結(jié)果:

ip

2.2 端口號

正在運(yùn)行的程序的標(biāo)識瞻惋,用于標(biāo)識進(jìn)程的邏輯地址厦滤,不同進(jìn)程的標(biāo)識援岩。有效端口:065535,其中01024系統(tǒng)使用或保留端口掏导。

端口分為:物理端口享怀,網(wǎng)卡口;邏輯端口趟咆,我們指的就是邏輯端口添瓷。

  • A:每個(gè)網(wǎng)絡(luò)程序都會至少有一個(gè)邏輯端口
  • B:用于標(biāo)識進(jìn)程的邏輯地址,不同進(jìn)程的標(biāo)識
  • C:有效端口:065535忍啸,其中01024系統(tǒng)使用或保留端口仰坦。
  • D:所謂防火墻,其功能就是將發(fā)送到某程序端口的數(shù)據(jù)屏蔽掉以及將從該程序端口發(fā)出的數(shù)據(jù)也屏蔽掉计雌。
端口號

2.3 傳輸協(xié)議

傳輸協(xié)議就是通訊的規(guī)則悄晃,常見協(xié)議:TCP,UDP凿滤。

UDP將數(shù)據(jù)源和目的封裝成數(shù)據(jù)包中妈橄,不需要建立連接;每個(gè)數(shù)據(jù)報(bào)的大小在限制在64k翁脆;因無連接眷蚓,是不可靠協(xié)議;不需要建立連接反番,速度快

TCP建立連接沙热,形成傳輸數(shù)據(jù)的通道;在連接中進(jìn)行大數(shù)據(jù)量傳輸罢缸;通過三次握手完成連接篙贸,是可靠協(xié)議;必須建立連接枫疆,效率會稍低

UDP和TCP的特點(diǎn)

  • UDP:面向無連接爵川;不可靠;速度快息楔;將數(shù)據(jù)封包傳輸寝贡,數(shù)據(jù)包最大64k
    舉例:聊天留言,在線視頻值依,視頻會議圃泡,發(fā)短信,郵局包裹愿险。
  • TCP:面向連接颇蜡;安全可靠效率稍低;通過三次握手確保連接的建立。
    舉例:下載澡匪,打電話,QQ聊天(你在線嗎,在線,就回應(yīng)下,就開始聊天了)

2.4 域名解析

域名解析

在瀏覽器中輸入新浪的域名褒链,DNS解析域名成IP唁情,然后計(jì)算機(jī)再通過獲取到的IP訪問新浪服務(wù)器。

域名解析甫匹,最先走是本地的hosts(C:\WINDOWS\system32\drivers\etc\hosts)文件甸鸟,解析失敗了,才去訪問DNS服務(wù)器解析兵迅、獲取IP地址抢韭。

域名解析
域名解析
import java.net.InetAddress;
import java.net.UnknownHostException;

public class IPDemo
{
    public static void main(String[] args) throws UnknownHostException {

        InetAddress ip = InetAddress.getLocalHost();

        ip = InetAddress.getByName("192.168.1.110");

        System.out.println(ip.getHostAddress());
        System.out.println(ip.getHostName());
    }
}

運(yùn)行結(jié)果

域名解析

應(yīng)用:通過hosts文件可以屏蔽游戲網(wǎng)站內(nèi)容彈出,例如:在hosts文件中添加恍箭,127.0.0.1 www.game18.com

3. Socket套接字

3.1 Socket套接字

網(wǎng)絡(luò)上具有唯一標(biāo)識的IP地址和端口號組合在一起才能構(gòu)成唯一能識別的標(biāo)識符套接字刻恭。

3.2 Socket原理機(jī)制

  • 通信的兩端都有Socket
  • 網(wǎng)絡(luò)通信其實(shí)就是Socket間的通信
  • 數(shù)據(jù)在兩個(gè)Socket間通過IO傳輸

3.3 Socket機(jī)制圖解

socket

4. UDP編程

UDP:UDP 協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議,在網(wǎng)絡(luò)中它與TCP 協(xié)議一樣用于處理數(shù)據(jù)包扯夭,是一種無連接的協(xié)議鳍贾。在OSI 模型中,在第四層——傳輸層交洗,處于IP 協(xié)議的上一層骑科。UDP 有不提供數(shù)據(jù)包分組、組裝和不能對數(shù)據(jù)包進(jìn)行排序的缺點(diǎn)构拳,也就是說咆爽,當(dāng)報(bào)文發(fā)送之后,是無法得知其是否安全完整到達(dá)的置森。UDP 用來支持那些需要在計(jì)算機(jī)之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用斗埂。包括網(wǎng)絡(luò)視頻會議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都需要使用UDP協(xié)議。UDP 協(xié)議從問世至今已經(jīng)被使用了很多年暇藏,雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋蜜笤,但是即使是在今天UDP 仍然不失為一項(xiàng)非常實(shí)用和可行的網(wǎng)絡(luò)傳輸層協(xié)議。

4.1 UDP傳輸

  • DatagramSocket與DatagramPacket
  • 建立發(fā)送端盐碱,接收端
  • 建立數(shù)據(jù)包
  • 調(diào)用Socket的發(fā)送接收方法
  • 關(guān)閉Socket
  • 發(fā)送端與接收端是兩個(gè)獨(dú)立的運(yùn)行程序

4.2 DatagramSocket

此類表示用來發(fā)送和接收數(shù)據(jù)報(bào)包的套接字

數(shù)據(jù)報(bào)套接字是包投遞服務(wù)的發(fā)送或接收點(diǎn)把兔。每個(gè)在數(shù)據(jù)報(bào)套接字上發(fā)送或接收的包都是單獨(dú)編址和路由的。從一臺機(jī)器發(fā)送到另一臺機(jī)器的多個(gè)包可能選擇不同的路由瓮顽,也可能按不同的順序到達(dá)

在 DatagramSocket 上總是啟用 UDP 廣播發(fā)送。為了接收廣播包暖混,應(yīng)該將 DatagramSocket 綁定到通配符地址缕贡。在某些實(shí)現(xiàn)中,將 DatagramSocket 綁定到一個(gè)更加具體的地址時(shí)廣播包也可以被接收。

構(gòu)造方法

DatagramSocket(int port) // 創(chuàng)建數(shù)據(jù)報(bào)套接字并將其綁定到本地主機(jī)上的指定端口
DatagramSocket(int port, InetAddress laddr) // 創(chuàng)建數(shù)據(jù)報(bào)套接字晾咪,將其綁定到指定的本地地址

UDP傳輸-發(fā)送端思路

  • 建立udp的socket服務(wù)
  • 將要發(fā)送的數(shù)據(jù)封裝成數(shù)據(jù)包
  • 通過udp的socket服務(wù),將數(shù)據(jù)包發(fā)送出
  • 關(guān)閉資源
package cn.itcast_02;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
 * UDP協(xié)議發(fā)送數(shù)據(jù):
 * A:創(chuàng)建發(fā)送端Socket對象
 * B:創(chuàng)建數(shù)據(jù)收擦,并把數(shù)據(jù)打包
 * C:調(diào)用Socket對象的發(fā)送方法發(fā)送數(shù)據(jù)包
 * D:釋放資源
 */
public class SendDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建發(fā)送端Socket對象
        // DatagramSocket()
        DatagramSocket ds = new DatagramSocket();

        // 創(chuàng)建數(shù)據(jù),并把數(shù)據(jù)打包
        // DatagramPacket(byte[] buf, int length, InetAddress address, int port)
        // 創(chuàng)建數(shù)據(jù)
        byte[] bys = "hello,udp,我來了".getBytes();
        // 長度
        int length = bys.length;
        // IP地址對象
        InetAddress address = InetAddress.getByName("192.168.12.92");
        // 端口
        int port = 10086;
        DatagramPacket dp = new DatagramPacket(bys, length, address, port);

        // 調(diào)用Socket對象的發(fā)送方法發(fā)送數(shù)據(jù)包
        // public void send(DatagramPacket p)
        ds.send(dp);

        // 釋放資源
        ds.close();
    }
}

4.3 DatagramPacket

此類表示數(shù)據(jù)報(bào)包谍倦。數(shù)據(jù)報(bào)包用來實(shí)現(xiàn)無連接包投遞服務(wù)塞赂。每條報(bào)文僅根據(jù)該包中包含的信息從一臺機(jī)器路由到另一臺機(jī)器。從一臺機(jī)器發(fā)送到另一臺機(jī)器的多個(gè)包可能選擇不同的路由昼蛀,也可能按不同的順序到達(dá)宴猾。不對包投遞做出保證。

構(gòu)造方法

  • DatagramPacket(byte[] buf, int length)
    構(gòu)造 DatagramPacket叼旋,用來接收長度為 length 的數(shù)據(jù)包仇哆。

  • DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    構(gòu)造數(shù)據(jù)報(bào)包,用來將長度為 length 的包發(fā)送到指定主機(jī)上的指定端口號夫植。

  • DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
    構(gòu)造數(shù)據(jù)報(bào)包讹剔,用來將長度為 length 偏移量為 offset 的包發(fā)送到指定主機(jī)上的指定端口號。

UDP傳輸-接收端思路

  • 建立udp的socket服務(wù).
  • 通過receive方法接收數(shù)據(jù)
  • 將收到的數(shù)據(jù)存儲到數(shù)據(jù)包對象中
  • 通過數(shù)據(jù)包對象的功能來完成對接收到數(shù)據(jù)進(jìn)行解析
  • 可以對資源進(jìn)行關(guān)閉
package cn.itcast_02;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * UDP協(xié)議接收數(shù)據(jù):
 * A:創(chuàng)建接收端Socket對象
 * B:創(chuàng)建一個(gè)數(shù)據(jù)包(接收容器)
 * C:調(diào)用Socket對象的接收方法接收數(shù)據(jù)
 * D:解析數(shù)據(jù)包详民,并顯示在控制臺
 * E:釋放資源
 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建接收端Socket對象
        // DatagramSocket(int port)
        DatagramSocket ds = new DatagramSocket(10086);

        // 創(chuàng)建一個(gè)數(shù)據(jù)包(接收容器)
        // DatagramPacket(byte[] buf, int length)
        byte[] bys = new byte[1024];
        int length = bys.length;
        DatagramPacket dp = new DatagramPacket(bys, length);

        // 調(diào)用Socket對象的接收方法接收數(shù)據(jù)
        // public void receive(DatagramPacket p)
        ds.receive(dp); // 阻塞式

        // 解析數(shù)據(jù)包辟拷,并顯示在控制臺
        // 獲取對方的ip
        // public InetAddress getAddress()
        InetAddress address = dp.getAddress();
        String ip = address.getHostAddress();
        // public byte[] getData():獲取數(shù)據(jù)緩沖區(qū)
        // public int getLength():獲取數(shù)據(jù)的實(shí)際長度
        byte[] bys2 = dp.getData();
        int len = dp.getLength();
        String s = new String(bys2, 0, len);
        System.out.println(ip + "傳遞的數(shù)據(jù)是:" + s);

        // 釋放資源
        ds.close();
    }
}

運(yùn)行結(jié)果:

udp

4.4 UDP案例

從鍵盤錄入數(shù)據(jù)進(jìn)行發(fā)送,如果輸入的是886那么客戶端就結(jié)束輸入數(shù)據(jù)阐斜。

發(fā)送端

package cn.itcast_04;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * 數(shù)據(jù)來自于鍵盤錄入
 * 鍵盤錄入數(shù)據(jù)要自己控制錄入結(jié)束衫冻。
 */
public class SendDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建發(fā)送端的Socket對象
        DatagramSocket ds = new DatagramSocket();

        // 封裝鍵盤錄入數(shù)據(jù)
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = br.readLine()) != null) {
            if ("886".equals(line)) {
                break;
            }

            // 創(chuàng)建數(shù)據(jù)并打包
            byte[] bys = line.getBytes();
            // DatagramPacket dp = new DatagramPacket(bys, bys.length,
            // InetAddress.getByName("192.168.12.92"), 12345);
            DatagramPacket dp = new DatagramPacket(bys, bys.length,
                    InetAddress.getByName("192.168.12.255"), 12345);

            // 發(fā)送數(shù)據(jù)
            ds.send(dp);
        }

        // 釋放資源
        ds.close();
    }
}

運(yùn)行結(jié)果:

udp

接收端

package cn.itcast_04;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
 * 多次啟動接收端:
 *      java.net.BindException: Address already in use: Cannot bind
 *      端口被占用。
 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建接收端的Socket對象
        DatagramSocket ds = new DatagramSocket(12345);

        while (true) {
            // 創(chuàng)建一個(gè)包裹
            byte[] bys = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);

            // 接收數(shù)據(jù)
            ds.receive(dp);

            // 解析數(shù)據(jù)
            String ip = dp.getAddress().getHostAddress();
            String s = new String(dp.getData(), 0, dp.getLength());
            System.out.println("from " + ip + " data is : " + s);
        }

        // 釋放資源
        // 接收端應(yīng)該一直開著等待接收數(shù)據(jù)谒出,是不需要關(guān)閉
        // ds.close();
    }
}

運(yùn)行結(jié)果:

udp

5. TCP編程

TCP/IP:Transmission Control Protocol/Internet Protocol 的簡寫隅俘,中譯名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議,又名網(wǎng)絡(luò)通訊協(xié)議笤喳,是Internet 最基本的協(xié)議为居、Internet 國際互聯(lián)網(wǎng)絡(luò)的基礎(chǔ),由網(wǎng)絡(luò)層的IP 協(xié)議和傳輸層的TCP協(xié)議組成杀狡。TCP/IP 定義了電子設(shè)備如何連入因特網(wǎng)蒙畴,以及數(shù)據(jù)如何在它們之間傳輸?shù)臉?biāo)準(zhǔn)。協(xié)議采用了4 層的層級結(jié)構(gòu)呜象,每一層都呼叫它的下一層所提供的協(xié)議來完成自己的需求膳凝。通俗而言:TCP 負(fù)責(zé)發(fā)現(xiàn)傳輸?shù)膯栴},一有問題就發(fā)出信號恭陡,要求重新傳輸蹬音,直到所有數(shù)據(jù)安全正確地傳輸?shù)侥康牡亍6鳬P 是給因特網(wǎng)的每一臺聯(lián)網(wǎng)設(shè)備規(guī)定一個(gè)地址休玩。

TCP/IP 協(xié)議棧主要分為四層:應(yīng)用層著淆、傳輸層劫狠、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層,每層都有相應(yīng)的協(xié)議永部,如下圖:

tcp

所謂的協(xié)議就是雙方進(jìn)行數(shù)據(jù)傳輸?shù)囊环N格式独泞。

5.1 TCP傳輸

  • Socket和ServerSocket
  • 建立客戶端和服務(wù)器端
  • 建立連接后,通過Socket中的IO流進(jìn)行數(shù)據(jù)的傳輸
  • 關(guān)閉socket
  • 同樣苔埋,客戶端與服務(wù)器端是兩個(gè)獨(dú)立的應(yīng)用程序阐肤。

5.2 Socket

此類實(shí)現(xiàn)客戶端套接字(也可以就叫“套接字”)。套接字是兩臺機(jī)器間通信的端點(diǎn)讲坎。

構(gòu)造方法

  • Socket(String host, int port) :創(chuàng)建一個(gè)流套接字并將其連接到指定主機(jī)上的指定端口號。
  • Socket(InetAddress address, int port) :創(chuàng)建一個(gè)流套接字并將其連接到指定 IP 地址的指定端口號愧薛。

TCP傳輸-客戶端思路

  • 建立客戶端的Socket服務(wù),并明確要連接的服務(wù)器晨炕。
  • 如果連接建立成功,就表明,已經(jīng)建立了數(shù)據(jù)傳輸?shù)耐ǖ?就可以在該通道通過IO進(jìn)行數(shù)據(jù)的讀取和寫入.該通道稱為Socket流,Socket流中既有讀取流,也有寫入流.
  • 通過Socket對象的方法,可以獲取這兩個(gè)流
  • 通過流的對象可以對數(shù)據(jù)進(jìn)行傳輸
  • 如果傳輸數(shù)據(jù)完畢,關(guān)閉資源
package cn.itcast_06;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/*
 * TCP協(xié)議發(fā)送數(shù)據(jù):
 * A:創(chuàng)建發(fā)送端的Socket對象
 *      這一步如果成功,就說明連接已經(jīng)建立成功了毫炉。
 * B:獲取輸出流瓮栗,寫數(shù)據(jù)
 * C:釋放資源
 *
 * 連接被拒絕。TCP協(xié)議一定要先看服務(wù)器瞄勾。
 * java.net.ConnectException: Connection refused: connect
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建發(fā)送端的Socket對象
        // Socket(InetAddress address, int port)
        // Socket(String host, int port)
        // Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
        Socket s = new Socket("192.168.12.92", 8888);

        // 獲取輸出流费奸,寫數(shù)據(jù)
        // public OutputStream getOutputStream()
        OutputStream os = s.getOutputStream();
        os.write("hello,tcp,我來了".getBytes());

        // 釋放資源
        s.close();
    }
}

5.3 ServerSocket

此類實(shí)現(xiàn)服務(wù)器套接字。服務(wù)器套接字等待請求通過網(wǎng)絡(luò)傳入进陡。它基于該請求執(zhí)行某些操作愿阐,然后可能向請求者返回結(jié)果。

構(gòu)造方法

ServerSocket(int port) // 創(chuàng)建綁定到特定端口的服務(wù)器套接字

TCP傳輸-服務(wù)器端思路

  • 建立服務(wù)器端的socket服務(wù)趾疚,需要一個(gè)端口
  • 服務(wù)端沒有直接流的操作,而是通過accept方法獲取客戶端對象缨历,在通過獲取到的客戶端對象的流和客戶端進(jìn)行通信
  • 通過客戶端的獲取流對象的方法,讀取數(shù)據(jù)或者寫入數(shù)據(jù)
  • 如果服務(wù)完成,需要關(guān)閉客戶端,然后關(guān)閉服務(wù)器,但是,一般會關(guān)閉客戶端,不會關(guān)閉服務(wù)器,因?yàn)榉?wù)端是一直提供服務(wù)的
package cn.itcast_06;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * TCP協(xié)議接收數(shù)據(jù):
 * A:創(chuàng)建接收端的Socket對象
 * B:監(jiān)聽客戶端連接糙麦。返回一個(gè)對應(yīng)的Socket對象
 * C:獲取輸入流辛孵,讀取數(shù)據(jù)顯示在控制臺
 * D:釋放資源
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建接收端的Socket對象
        // ServerSocket(int port)
        ServerSocket ss = new ServerSocket(8888);

        // 監(jiān)聽客戶端連接。返回一個(gè)對應(yīng)的Socket對象
        // public Socket accept()
        Socket s = ss.accept(); // 偵聽并接受到此套接字的連接赡磅。此方法在連接傳入之前一直阻塞魄缚。

        // 獲取輸入流,讀取數(shù)據(jù)顯示在控制臺
        InputStream is = s.getInputStream();

        byte[] bys = new byte[1024];
        int len = is.read(bys); // 阻塞式方法
        String str = new String(bys, 0, len);

        String ip = s.getInetAddress().getHostAddress();

        System.out.println(ip + "---" + str);

        // 釋放資源
        s.close();
        // ss.close(); //這個(gè)不應(yīng)該關(guān)閉
    }
}

5.4 TCP傳輸案例

客戶端鍵盤錄入焚廊,服務(wù)器輸出到控制臺

客戶端:

package cn.itcast_08;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/*
 * 客戶端鍵盤錄入冶匹,服務(wù)器輸出到控制臺
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 22222);

        // 鍵盤錄入數(shù)據(jù)
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 把通道內(nèi)的流給包裝一下
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));

        String line = null;
        while ((line = br.readLine()) != null) {
            // 鍵盤錄入數(shù)據(jù)要自定義結(jié)束標(biāo)記
            if ("886".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        // 釋放資源
        // bw.close();
        // br.close();
        s.close();
    }
}

運(yùn)行結(jié)果:

tcp

服務(wù)器端:

package cn.itcast_08;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建服務(wù)器Socket對象
        ServerSocket ss = new ServerSocket(22222);

        // 監(jiān)聽客戶端連接
        Socket s = ss.accept();

        // 包裝通道內(nèi)容的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }

        // br.close();
        s.close();
        // ss.close();
    }
}

運(yùn)行結(jié)果:

tcp

5.5 上傳圖片案例

客戶端:

package cn.itcast_13;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class UploadClient {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 19191);

        // 封裝圖片文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "林青霞.jpg"));
        // 封裝通道內(nèi)的流
        BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }

        s.shutdownOutput();

        // 讀取反饋
        InputStream is = s.getInputStream();
        byte[] bys2 = new byte[1024];
        int len2 = is.read(bys2);
        String client = new String(bys2, 0, len2);
        System.out.println(client);

        // 釋放資源
        bis.close();
        s.close();
    }
}

服務(wù)器端:

package cn.itcast_13;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建服務(wù)器Socket對象
        ServerSocket ss = new ServerSocket(19191);

        // 監(jiān)聽客戶端連接
        Socket s = ss.accept();

        // 封裝通道內(nèi)流
        BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
        // 封裝圖片文件
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("mn.jpg"));

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }

        // 給一個(gè)反饋
        OutputStream os = s.getOutputStream();
        os.write("圖片上傳成功".getBytes());

        bos.close();
        s.close();
    }
}

運(yùn)行結(jié)果:

tcp

5.6 TCP傳輸容易出現(xiàn)的問題

  • 客戶端連接上服務(wù)端,兩端都在等待咆瘟,沒有任何數(shù)據(jù)傳輸
  • 通過例程分析:因?yàn)閞ead方法或者readLine方法是阻塞式
  • 解決辦法:自定義結(jié)束標(biāo)記徙硅,使用shutdownInput,shutdownOutput方法

6. TCP搞疗、UDP 特點(diǎn)對比

TCP 協(xié)議是面向連接嗓蘑、保證高可靠性(數(shù)據(jù)無丟失须肆、數(shù)據(jù)無失序、數(shù)據(jù)無錯(cuò)誤桩皿、數(shù)據(jù)無重復(fù)到達(dá))傳輸層協(xié)議豌汇。UDP 協(xié)議也是傳輸層協(xié)議,它是無連接泄隔,不保證可靠的傳輸層協(xié)議拒贱。

TCP UDP
面向連接 面向非連接
可靠的連接 不可靠的連接
速度慢 速度快
大文件、重要的數(shù)據(jù)等 適合小數(shù)據(jù)佛嬉、不重要

7. TCP 三次握手過程

1逻澳、請求端(通常稱為客戶)發(fā)送一個(gè)SYN 段指明客戶打算連接的服務(wù)器的端口,以及初始序號(ISN)

2暖呕、服務(wù)器發(fā)回包含服務(wù)器的初始序號的SYN 報(bào)文段(報(bào)文段2)作為應(yīng)答斜做。同時(shí),將確認(rèn)序號設(shè)置為客戶的ISN加1 以對客戶的SYN 報(bào)文段進(jìn)行確認(rèn)湾揽。

3瓤逼、客戶必須將確認(rèn)序號設(shè)置為服務(wù)器的ISN 加1 以對服務(wù)器的SYN 報(bào)文段進(jìn)行確認(rèn)(報(bào)文段3)這三個(gè)報(bào)文段完成連接的建立。這個(gè)過程也稱為三次握手(three-way handshake)库物。

上面的過程如下圖所示:

tcp

8. 客戶端和服務(wù)器端原理

8.1 常見的客戶端霸旗、服務(wù)器端

最常見的客戶端:瀏覽器,IE/chrome
最常見的服務(wù)端:服務(wù)器戚揭,Tomcat

8.2 常見網(wǎng)絡(luò)結(jié)構(gòu)

網(wǎng)絡(luò)結(jié)構(gòu)

8.3 URL&URI

URI:統(tǒng)一資源標(biāo)識符

URI是統(tǒng)一資源標(biāo)識符诱告,是一個(gè)用于標(biāo)識某一互聯(lián)網(wǎng)資源名稱的字符串。 該種標(biāo)識允許用戶對任何(包括本地和互聯(lián)網(wǎng))的資源通過特定的協(xié)議進(jìn)行交互操作民晒。URI由包括確定語法和相關(guān)協(xié)議的方案所定義蔬啡。由是三個(gè)組成部分:訪問資源的命名機(jī)制、存放資源的主機(jī)名镀虐、資源自身的名稱箱蟆,由路徑表示。

URL:統(tǒng)一資源定位符

也就是說根據(jù)URL能夠定位到網(wǎng)絡(luò)上的某個(gè)資源刮便,它是指向互聯(lián)網(wǎng)“資源”的指針空猜。

每個(gè)URL都是URI,但不一定每個(gè)URI都是URL恨旱。這是因?yàn)閁RI還包括一個(gè)子類辈毯,即統(tǒng)一資源名稱(URN),它命名資源但不指定如何定位資源搜贤。

URL是統(tǒng)一資源定位谆沃,是對可以從互聯(lián)網(wǎng)上得到的資源的位置和訪問方法的一種簡潔的表示,是互聯(lián)網(wǎng)上標(biāo)準(zhǔn)資源的地址仪芒⊙溆埃互聯(lián)網(wǎng)上的每個(gè)文件都有一個(gè)唯一的URL耕陷,它包含的信息指出文件的位置以及瀏覽器應(yīng)該怎么處理它。

比如百度URL即是http://www.baidu.com据沈。

9. TCP的三次握手/四次揮手

TCP是面向連接的運(yùn)輸層協(xié)議哟沫,TCP協(xié)議提供可靠的連接服務(wù),所以用了建立鏈接的三次握手和關(guān)閉連接的四次揮手來保證可靠服務(wù)锌介。
通過TCP通信就像是兩個(gè)應(yīng)用在打電話一樣嗜诀,打電話前得先撥號建立連接,通話結(jié)束后要掛機(jī)釋放連接孔祸。

9.1 建立TCP連接的三次握手

TCP連接的三次握手分別為:

  • 客戶端發(fā)送一個(gè)帶SYN標(biāo)志的TCP報(bào)文到服務(wù)器隆敢,表示告訴服務(wù)器我想建立一個(gè)連接。
  • 服務(wù)器收到客戶端的帶SYN標(biāo)志的文后崔慧,就給客戶端回復(fù)一個(gè)帶ACK標(biāo)志和帶SYN標(biāo)志的報(bào)文拂蝎,ACK表示回復(fù)客戶端:OK,我準(zhǔn)備好了建立連接尊浪;然后SYN表示服務(wù)器又問客戶端:你準(zhǔn)備好建立連接了么?
  • 然后客戶端又要發(fā)送一個(gè)帶ACK標(biāo)志的TCP報(bào)文封救,回答服務(wù)器說:我準(zhǔn)備好了拇涤。
    然后一個(gè)TCP連接就建立起來了。

SYN相當(dāng)于詢問的標(biāo)志誉结,ACK相當(dāng)于回復(fù)的標(biāo)志鹅士。

這里有一個(gè)問題:為什么最后客戶端還要發(fā)送一次確認(rèn)呢?這主要是防止已經(jīng)失效了的請求報(bào)文段突然又傳到了服務(wù)器惩坑,因而產(chǎn)生錯(cuò)誤掉盅。
“已經(jīng)失效了的請求報(bào)文段”大致是這樣產(chǎn)生的:A發(fā)出第一個(gè)連接請求報(bào)文段并沒有丟失,在一些網(wǎng)絡(luò)結(jié)點(diǎn)上面長時(shí)間滯留以舒,以致延誤到連接釋放以后的某個(gè)時(shí)間才到達(dá)B趾痘。本來這是一個(gè)早已失效的報(bào)文段。但B收到這個(gè)失效的報(bào)文段后蔓钟,就誤以為是A發(fā)出的又一次新的連接請求永票,于是就向A發(fā)出確認(rèn)報(bào)文段,同意建立連接滥沫,如果不采用三次握手侣集,那么只要B發(fā)出確認(rèn)后,新的連接就建立了兰绣。

9.2 釋放TCP連接的四次揮手

由于TCP是全雙工的世分,所以在釋放TCP連接時(shí),要雙方都得單獨(dú)關(guān)閉缀辩。意思就是服務(wù)器和客戶端都要釋放連接臭埋。原則是某一方主動關(guān)閉時(shí)踪央,先發(fā)一個(gè)FIN報(bào)文來表示終止這個(gè)方向的連接,收到一個(gè)FIN報(bào)文就意味著這個(gè)方向不再有數(shù)據(jù)流動斋泄,但另一個(gè)方向仍可以有數(shù)據(jù)流動杯瞻,當(dāng)這一個(gè)方向也發(fā)送了FIN報(bào)文后,那么這一方的連接也可以關(guān)閉了炫掐。
釋放TCP連接相對于要復(fù)雜點(diǎn)魁莉,具體釋放TCP連接的四次揮手流程如下:

  • A發(fā)送一個(gè)FIN給B,說:我這邊要傳給你的數(shù)據(jù)已經(jīng)傳完了募胃,我要關(guān)閉連接了旗唁。A進(jìn)入FIN-WAIT-1狀態(tài),等待B確認(rèn)痹束。
  • B收到了上面的FIN報(bào)文后检疫,回復(fù)一個(gè)ACK報(bào)文說:OK。A就關(guān)閉了A->B的連接祷嘶。但是此時(shí)B還能給A發(fā)送數(shù)據(jù)屎媳,A也能接收B發(fā)來的數(shù)據(jù)。(此時(shí)A收到確認(rèn)后進(jìn)入FIN-WAIT-2狀態(tài)论巍。TCP處于半關(guān)閉狀態(tài))
  • 當(dāng)B也發(fā)送完數(shù)據(jù)后烛谊,就給A發(fā)送一個(gè)FIN報(bào)文說:我這邊要傳給你的數(shù)據(jù)也已經(jīng)傳完了,我也要關(guān)閉連接了嘉汰。(B進(jìn)入LAST-ACK狀態(tài)丹禀,等待A確認(rèn))
  • A收到了上面的報(bào)文后,回復(fù)一個(gè)ACK報(bào)文說:OK鞋怀。A進(jìn)入TIME-WAIT狀態(tài)∷幔現(xiàn)在TCP連接還沒有釋放掉,然后經(jīng)過等待計(jì)時(shí)器(TIME-WAIT timer)設(shè)置的時(shí)間2MSL后密似,A才進(jìn)入CLOSE狀態(tài)焙矛。

然后,當(dāng)A撤銷相應(yīng)的傳輸控制塊TCB后残腌,一個(gè)TCP連接就關(guān)閉了薄扁。

10. Http、Tcp废累、Udp邓梅、Socket的區(qū)別

IP,網(wǎng)絡(luò)層協(xié)議邑滨;TCP和UDP日缨,傳輸層協(xié)議;HTTP掖看,應(yīng)用層協(xié)議匣距;SOCKET:TCP/IP網(wǎng)絡(luò)的API面哥。

TCP/IP代表傳輸控制協(xié)議/網(wǎng)際協(xié)議,指的是一系列協(xié)議毅待。

TCP和UDP使用IP協(xié)議從一個(gè)網(wǎng)絡(luò)傳送數(shù)據(jù)包到另一個(gè)網(wǎng)絡(luò)尚卫。把IP想像成一種高速公路,它允許其它協(xié)議在上面行駛并找到到其它電腦的出口尸红。TCP和UDP是高速公路上的“卡車”吱涉,它們攜帶的貨物就是像HTTP,文件傳輸協(xié)議FTP這樣的協(xié)議等外里。

TCP和UDP是FTP怎爵,HTTP和SMTP之類使用的傳輸層協(xié)議。雖然TCP和UDP都是用來傳輸其他協(xié)議的盅蝗,它們卻有一個(gè)顯著的不同:TCP提供有保證的數(shù)據(jù)傳輸鳖链,而UDP不提供。這意味著TCP有一個(gè)特殊的機(jī)制來確保數(shù)據(jù)安全的不出錯(cuò)的從一個(gè)端點(diǎn)傳到另一個(gè)端點(diǎn)墩莫,而UDP不提供任何這樣的保證芙委。

HTTP(超文本傳輸協(xié)議)是利用TCP在兩臺電腦(通常是Web服務(wù)器和客戶端)之間傳輸信息的協(xié)議】袂兀客戶端使用Web瀏覽器發(fā)起HTTP請求給Web服務(wù)器灌侣,Web服務(wù)器發(fā)送被請求的信息給客戶端。

記住故痊,需要IP協(xié)議來連接網(wǎng)絡(luò);TCP是一種允許我們安全傳輸數(shù)據(jù)的機(jī)制顶瞳,使用TCP協(xié)議來傳輸數(shù)據(jù)的HTTP是Web服務(wù)器和客戶端使用的特殊協(xié)議玖姑。

Socket 接口是TCP/IP網(wǎng)絡(luò)的API愕秫,Socket接口定義了許多函數(shù)或例程,用以開發(fā)TCP/IP網(wǎng)絡(luò)上的應(yīng)用程序焰络。

本節(jié)原文鏈接:http://www.reibang.com/p/1f512687ea19

11. URL

URI:統(tǒng)一資源標(biāo)示符戴甩。

URL:統(tǒng)一資源定位符,也就是說根據(jù)URL能夠定位到網(wǎng)絡(luò)上的某個(gè)資源闪彼,它是指向互聯(lián)網(wǎng)“資源”的指針甜孤。

每個(gè)URL都是URI,但不一定每個(gè)URI都是URL畏腕。這是因?yàn)閁RI還包括一個(gè)子類缴川,即統(tǒng)一資源名稱(URN),它命名資源但不指定如何定位資源描馅。

public class URLDemo
{
    public static void main(String[] args) throws MalformedURLException,IOException {
        String str_url = "http://192.168.1.100:8080/myweb/1.html?name=lisi";
        URL url = new URL(str_url);
        System.out.println("getProtocol:" + url.getProtocol());
        System.out.println("getHost:" + url.getHost());
        System.out.println("getPort:" + url.getPort());
        System.out.println("getFile:" + url.getFile());
        System.out.println("getPath:" + url.getPath());
        System.out.println("getQuery:" + url.getQuery());
        InputStream in = url.openStream();//相當(dāng)于 url.openConnection().getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        String text = new String(buf,0,len);
        System.out.println(text);
        in.close();
    }
}

運(yùn)行結(jié)果

url

之所以運(yùn)行結(jié)果中響應(yīng)頭不見了把夸,只能看到主體數(shù)據(jù)的原因在于:URLConnection對象已經(jīng)把響應(yīng)頭
給解析了

12. URLConnection

public class URLDemo
{
    public static void main(String[] args) throws MalformedURLException,IOException {
        String str_url = "http://192.168.1.100:8080/myweb/1.html?name=lisi";
        URL url = new URL(str_url);
        //獲取url對象的Url連接器對象。將連接封裝成了對象:
        // java中內(nèi)置的可以解析的具體協(xié)議對象+socket铭污。
        URLConnection conn = url.openConnection();
        System.out.println(conn);
        //由于URLConnection對象已經(jīng)把響應(yīng)頭給解析了恋日,所以膀篮,
        // 可以通過URLConnection對象獲取響應(yīng)頭某屬性名對應(yīng)的屬性值。
        String value = conn.getHeaderField("Content-Type");
        System.out.println(value);
    }
}

運(yùn)行結(jié)果

urlconnection

13. HttpURLConnection

URL newURL = new URL(url);
URLConnection urlConnection = newURL.openConnection();
urlConnection.setConnectTimeout(mConfig.connTimeOut);
urlConnection.setReadTimeout(mConfig.soTimeOut);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);

// HttpsURLConnection
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
HttpsURLConnection.setDefaultHostnameVerifier();

HttpURLConnection常用方法

方法聲明 功能描述
addRequestProperty() 添加請求屬性
setRequestMethod() 設(shè)置請求方式
connect() 連接網(wǎng)絡(luò)
disconnect() 斷開連接
setDoOutput() 設(shè)置打開連接對象輸出流岂膳,把要提交的數(shù)據(jù)寫入流中
setDoInput() 設(shè)置打開連接對象輸入流
setConnectTimeout() 設(shè)置連接超時(shí)
setReadTimeout() 設(shè)置讀取超時(shí)
setUseCaches() 設(shè)置是否使用緩存
getResponseCode() 獲取響應(yīng)碼
getOutputStream() 獲取輸出流
getInputStream() 獲取輸入流
getErrorStream() 獲取錯(cuò)誤流
getResponseMessage() 獲取響應(yīng)信息
getContentLength() 獲取內(nèi)容長度
getContentEncoding() 獲取內(nèi)容編碼
getContentType() 獲取內(nèi)容類型
getHeaderFields() 獲取所有的頭字段

setRequestProperty和addRequestProperty的區(qū)別

setRequestProperty和addRequestProperty的區(qū)別就是誓竿,setRequestProperty會覆蓋已經(jīng)存在的key的所有values,有清零重新賦值的作用谈截。而addRequestProperty則是在原來key的基礎(chǔ)上繼續(xù)添加其他value筷屡。

/**
 * Adds the given property to the request header. Existing properties with
 * the same name will not be overwritten by this method.
 */
 public void addRequestProperty(String field, String newValue) {
        ...
    }

字節(jié)流轉(zhuǎn)換為字符

public class Tools {
    public static String getTextFromStream(InputStream is) {
        try {
            byte[] b = new byte[1024];
            int len;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while ((len = is.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            //把輸出流里的內(nèi)容轉(zhuǎn)換成字節(jié)數(shù)組
            String text = new String(bos.toByteArray());
            return text;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

14. URLEncoder和URLDecoder

URLEncoder.encode();
URLDecoder.decode();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市傻盟,隨后出現(xiàn)的幾起案子速蕊,更是在濱河造成了極大的恐慌,老刑警劉巖娘赴,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件规哲,死亡現(xiàn)場離奇詭異,居然都是意外死亡诽表,警方通過查閱死者的電腦和手機(jī)唉锌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來竿奏,“玉大人袄简,你說我怎么就攤上這事》盒ィ” “怎么了绿语?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長候址。 經(jīng)常有香客問我吕粹,道長,這世上最難降的妖魔是什么岗仑? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任匹耕,我火速辦了婚禮,結(jié)果婚禮上荠雕,老公的妹妹穿的比我還像新娘稳其。我一直安慰自己,他們只是感情好炸卑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布既鞠。 她就那樣靜靜地躺著,像睡著了一般盖文。 火紅的嫁衣襯著肌膚如雪嘱蛋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音浑槽,去河邊找鬼蒋失。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桐玻,可吹牛的內(nèi)容都是我干的篙挽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼镊靴,長吁一口氣:“原來是場噩夢啊……” “哼铣卡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起偏竟,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤煮落,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后踊谋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝉仇,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年殖蚕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轿衔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡睦疫,死狀恐怖害驹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蛤育,我是刑警寧澤宛官,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瓦糕,受9級特大地震影響底洗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刻坊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一蜒茄、第九天 我趴在偏房一處隱蔽的房頂上張望精置。 院中可真熱鬧,春花似錦颈嚼、人聲如沸未玻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扳剿。三九已至旁趟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庇绽,已是汗流浹背锡搜。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工橙困, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耕餐。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓凡傅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肠缔。 傳聞我的和親對象是個(gè)殘疾皇子夏跷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記明未,這雖然只是...
    貳零壹柒_fc10閱讀 5,054評論 0 8
  • 1.這篇文章不是本人原創(chuàng)的槽华,只是個(gè)人為了對這部分知識做一個(gè)整理和系統(tǒng)的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,068評論 6 174
  • 短篇集趟妥。三個(gè)短篇猫态,前兩個(gè)不錯(cuò)!很有創(chuàng)意披摄!總的來說還是有點(diǎn)太陰暗懂鸵、負(fù)面了! 內(nèi)容簡介:(摘自網(wǎng)絡(luò)) 《只有你聽到Ca...
    烏麗曼閱讀 1,197評論 0 1
  • 每個(gè)人都希望他們有更好的面試問題行疏。因此匆光,我咨詢了各個(gè)領(lǐng)域中的創(chuàng)始人或CEO,問了他們最喜愛的面試問題是什么以及這些...
    小好閱讀 848評論 0 4
  • 生活在 Linux 下酿联,折騰肯定是少不了的终息,所以玩壞的情況也是常有的事情。如果有一臺時(shí)光機(jī)器可以讓系統(tǒng)回到某個(gè)時(shí)間...
    左藍(lán)閱讀 6,285評論 0 9