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ù)鏈路層
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)卡出問題了
通過ping命令還可以獲取到url對應(yīng)的IP地址,例如獲取網(wǎng)易新聞url(c.m.163.com)的IP地址
查看本機(jī)IP地址ipconfig
IP地址分類
IP地址的組成:IP地址 = 網(wǎng)絡(luò)號碼+主機(jī)地址
IPV4數(shù)量已經(jīng)不夠分配拨齐,所以產(chǎn)生了IPV6鳞陨。
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é)果:
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ī)制圖解
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é)果:
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é)果:
接收端
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é)果:
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é)議永部,如下圖:
所謂的協(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é)果:
服務(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é)果:
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é)果:
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)库物。
上面的過程如下圖所示:
8. 客戶端和服務(wù)器端原理
8.1 常見的客戶端霸旗、服務(wù)器端
最常見的客戶端:瀏覽器,IE/chrome
最常見的服務(wù)端:服務(wù)器戚揭,Tomcat
8.2 常見網(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é)果
之所以運(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é)果
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();