TCP和UDP在網(wǎng)絡(luò)傳輸中非常重要,在Android開發(fā)中同樣重要。
首先我們來看一下什么是TCP和UDP。
什么是TCP?
TCP:Transmission Control Protocol 傳輸控制協(xié)議TCP是一種面向連接(連接導(dǎo)向)的、可靠的、基于字節(jié)流的運(yùn)輸層(Transport layer)通信協(xié)議,由IETF的RFC 793說明(specified)。在簡化的計(jì)算機(jī)網(wǎng)絡(luò)OSI模型中,它完成第四層傳輸層所指定的功能。應(yīng)用層向TCP層發(fā)送用于網(wǎng)間傳輸?shù)摹⒂?位字節(jié)表示的數(shù)據(jù)流,然后TCP把數(shù)據(jù)流分割成適當(dāng)長度的報(bào)文段(通常受該計(jì)算機(jī)連接的網(wǎng)絡(luò)的數(shù)據(jù)鏈路層的最大傳送單元(MTU)的限制)。之后TCP把結(jié)果包傳給IP層,由它來通過網(wǎng)絡(luò)將包傳送給接收端實(shí)體的TCP層。TCP為了保證不發(fā)生丟包,就給每個(gè)字節(jié)一個(gè)序號(hào),同時(shí)序號(hào)也保證了傳送到接收端實(shí)體的包的按序接收。然后接收端實(shí)體對(duì)已成功收到的字節(jié)發(fā)回一個(gè)相應(yīng)的確認(rèn)(ACK);如果發(fā)送端實(shí)體在合理的往返時(shí)延(RTT)內(nèi)未收到確認(rèn),那么對(duì)應(yīng)的數(shù)據(jù)(假設(shè)丟失了)將會(huì)被重傳。TCP用一個(gè)校驗(yàn)和函數(shù)來檢驗(yàn)數(shù)據(jù)是否有錯(cuò)誤;在發(fā)送和接收時(shí)都要計(jì)算校驗(yàn)和。
首先,TCP建立連接之后,通信雙方都同時(shí)可以進(jìn)行數(shù)據(jù)的傳輸,其次,他是全雙工的;在保證可靠性上,采用超時(shí)重傳和捎帶確認(rèn)機(jī)制。
在流量控制上,采用滑動(dòng)窗口協(xié)議[1],協(xié)議中規(guī)定,對(duì)于窗口內(nèi)未經(jīng)確認(rèn)的分組需要重傳。
在擁塞控制上,采用慢啟動(dòng)算法。
什么是UDP?
UDP 是User Datagram Protocol的簡稱, 中文名是用戶數(shù)據(jù)包協(xié)議,是 OSI 參考模型中一種無連接的傳輸層協(xié)議,提供面向事務(wù)的簡單不可靠信息傳送服務(wù)。它是IETF RFC 768是UDP的正式規(guī)范。在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包。在OSI模型中,在第四層——傳輸層,處于IP協(xié)議的上一層。UDP有不提供數(shù)據(jù)報(bào)分組、組裝和不能對(duì)數(shù)據(jù)包的排序的缺點(diǎn),也就是說,當(dāng)報(bào)文發(fā)送之后,是無法得知其是否安全完整到達(dá)的。 UDP用來支持那些需要在計(jì)算機(jī)之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用。包括網(wǎng)絡(luò)視頻會(huì)議系統(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é)議。
與所熟知的TCP(傳輸控制協(xié)議)協(xié)議一樣,UDP協(xié)議直接位于IP(網(wǎng)際協(xié)議)協(xié)議的頂層。根據(jù)OSI(開放系統(tǒng)互連)參考模型,UDP和TCP都屬于傳輸層協(xié)議。
UDP協(xié)議的主要作用是將網(wǎng)絡(luò)數(shù)據(jù)流量壓縮成數(shù)據(jù)報(bào)的形式。一個(gè)典型的數(shù)據(jù)報(bào)就是一個(gè)二進(jìn)制數(shù)據(jù)的傳輸單位。每一個(gè)數(shù)據(jù)報(bào)的前8個(gè)字節(jié)用來包含報(bào)頭信息,剩余字節(jié)則用來包含具體的傳輸數(shù)據(jù)。
TCP和UDP在android中的使用和在Java里是完全一樣的。
首先我們看看TCP連接,下圖為TCP連接的一個(gè)示意圖:
TCP傳輸原理
是不是很好理解,這里就不多說了,直接看代碼吧!實(shí)踐出真知。
TCP服務(wù)器端代碼:
try {
Boolean endFlag = false;
ServerSocket ss = new ServerSocket(12345);
while (!endFlag) {
// 等待客戶端連接
Socket s = ss.accept();
BufferedReader input = new BufferedReader(newInputStreamReader(s.getInputStream()));
//注意第二個(gè)參數(shù)據(jù)為true將會(huì)自動(dòng)flush,否則需要需要手動(dòng)操作output.flush()
PrintWriter output = newPrintWriter(s.getOutputStream(),true);
String message = input.readLine();
Log.d(“Tcp Demo”, “message from Client:”+message);
output.println(“message received!”);
//output.flush();
if(“shutDown”.equals(message)){
endFlag=true;
}
s.close();
}
ss.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
TCP客戶端代碼:
try {
Socket s = new Socket(“localhost”, 12345);
// outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
// 注意第二個(gè)參數(shù)據(jù)為true將會(huì)自動(dòng)flush,否則需要需要手動(dòng)操作out.flush()
PrintWriter output = new PrintWriter(out, true);
output.println(“Hello IdeasAndroid!”);
BufferedReader input = new BufferedReader(newInputStreamReader(s
.getInputStream()));
// read line(s)
String message = input.readLine();
Log.d(“Tcp Demo”, “message From Server:” + message);
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
下面我們看看UDP:
UDP傳輸原理
UDP服務(wù)器端代碼:
// UDP服務(wù)器監(jiān)聽的端口
Integer port = 12345; // 接收的字節(jié)大小,客戶端發(fā)送的數(shù)據(jù)不能超過這個(gè)大小
byte[] message = new byte[1024];
try {
// 建立Socket連接
DatagramSocket datagramSocket = new DatagramSocket(port);
DatagramPacket datagramPacket = new DatagramPacket(message,
message.length);
try {
while (true) {
// 準(zhǔn)備接收數(shù)據(jù)
datagramSocket.receive(datagramPacket);
Log.d(“UDP Demo”, datagramPacket.getAddress()
.getHostAddress().toString()
+ “:” + new String(datagramPacket.getData()));
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (SocketException e) {
e.printStackTrace();
}
UDP客戶端代碼:
public static void send(String message) {
message = (message == null ? “Hello IdeasAndroid!” : message);
int server_port = 12345;
DatagramSocket s = null;
try {
s = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
InetAddress local = null;
try {
// 換成服務(wù)器端IP
local = InetAddress.getByName(“localhost”);
} catch (UnknownHostException e) {
e.printStackTrace();
}
int msg_length = message.length();
byte[] messagemessageByte = message.getBytes();
DatagramPacket p = new DatagramPacket(messageByte, msg_length, local,
server_port);
try {
s.send(p);
} catch (IOException e) {
e.printStackTrace();
}
}
代碼中需要注意的地方已做了注釋,希望本文對(duì)您有所幫助!