一.區別
二者都是有用的和常用的,如果純粹從概念上區分二者就比較費解了,我們直接從功能上進行區分,簡單明瞭:
這兩種傳輸協議也就是合於適配不同的業務和不同的硬件終端。
在使用中,類似於圖像、聲音等對可靠性要求沒有那麼高的業務可以用UDP,他們不需要準確存儲對準確性無要求但要求速度快。
類似於文本、程序、文件等要求可靠的數據最好就用TCP,但會犧牲一些速度。
對系統資源的要求:CP較多,UDP少。
程序結構:UDP程序結構較簡單,TCP複雜。
流模式與數據報模式:TCP保證數據正確性,UDP可能丟包; TCP保證數據順序,UDP不保證
二.用途
TCP是面向連接的,有比較高的可靠性,一些要求比較高的服務一般使用這個協議,如FTP、Telnet、SMTP、HTTP、POP3等,而UDP是面向無連接的,使用這個協議的常見服務有DNS、SNMP、QQ等。對於QQ必須另外說明一下,QQ2003以前是隻使用UDP協議的,其服務器使用8000端口,偵聽是否有信息傳來,客戶端使用4000端口,向外發送信息(這也就不難理解在一般的顯IP的QQ版本中顯示好友的IP地址信息中端口常爲4000或其後續端口的原因了),即QQ程序既接受服務又提供服務,在以後的QQ版本中也支持使用TCP協議了。
Udp是一種面向無連接的通信協議,該協議使得數據傳輸的速度得到大幅度的提高。視頻聊天語音聊天基本都是用UPD協議。
三.例子
TCP: ServerSocket ss = new ServerSocket(2000);
UDP: 創建DatagramSocket對象,DatagramSocket區別於Tcp方式下的socket對象。
DatagramSocket ds=new DatagramSocket();
下面是具體的程序代碼,已經編譯通過,另外附件也是源碼可以直接下載。
TCP服務器端
TCP客戶端
------------------------------------------------------------
UDP服務器端
UDP客戶端
更多TCP和UPD的資料:
TCP---傳輸控制協議,提供的是面向連接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間建立一個TCP連接,之後才能傳輸數 據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。
UDP---用戶數據報協議,是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,但是並不能保證它 們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快。
UDP 與 TCP 的主要區別在於 UDP 不一定提供可靠的數據傳輸。事實上,該協議不能保證數據準確無誤地到達目的地。UDP 在許多方面非常有效。當某個程序的目標是儘快地傳輸儘可能多的信息時(其中任意給定數據的重要性相對較低),可使用 UDP。ICQ 短消息使用 UDP 協議發送消息。
許多程序將使用單獨的TCP連接和單獨的UDP連接。重要的狀態信息隨可靠的TCP連接發送,而主數據流通過UDP發送。
TCP的目的是提供可靠的數據傳輸,並在相互進行通信的設備或服務之間保持一個虛擬連接。TCP在數據包接收無序、丟失或在交付期間被破壞時,負責數據恢 復。它通過爲其發送的每個數據包提供一個序號來完成此恢復。記住,較低的網絡層會將每個數據包視爲一個獨立的單元,因此,數據包可以沿完全不同的路徑發 送,即使它們都是同一消息的組成部分。這種路由與網絡層處理分段和重新組裝數據包的方式非常相似,只是級別更高而已。
爲確保正確地接收數據,TCP要求在目標計算機成功收到數據時發回一個確認(即 ACK)。如果在某個時限內未收到相應的 ACK,將重新傳送數據包。如果網絡擁塞,這種重新傳送將導致發送的數據包重複。但是,接收計算機可使用數據包的序號來確定它是否爲重複數據包,並在必要 時丟棄它。
TCP與UDP的選擇
如果比較UDP包和TCP包的結構,很明顯UDP包不具備TCP包複雜的可靠性與控制機制。與TCP協議相同,UDP的源端口數和目的端口數也都支持一臺 主機上的多個應用。一個16位的UDP包包含了一個字節長的頭部和數據的長度,校驗碼域使其可以進行整體校驗。(許多應用只支持UDP,如:多媒體數據 流,不產生任何額外的數據,即使知道有破壞的包也不進行重發。)
很明顯,當數據傳輸的性能必須讓位於數據傳輸的完整性、可控制性和可靠性時,TCP協議是當然的選擇。當強調傳輸性能而不是傳輸的完整性時,如:音頻和多 媒體應用,UDP是最好的選擇。在數據傳輸時間很短,以至於此前的連接過程成爲整個流量主體的情況下,UDP也是一個好的選擇,如:DNS交換。把 SNMP建立在UDP上的部分原因是設計者認爲當發生網絡阻塞時,UDP較低的開銷使其有更好的機會去傳送管理數據。TCP豐富的功能有時會導致不可預料 的性能低下,但是我們相信在不遠的將來,TCP可靠的點對點連接將會用於絕大多數的網絡應用。
FTP協議即文件傳輸協議,它是一個標準協議,FTP協議也是應用TCP/IP協議的應用協議標準,它是在計算機和網絡之間交換文件的最簡單的方法。
二者都是有用的和常用的,如果純粹從概念上區分二者就比較費解了,我們直接從功能上進行區分,簡單明瞭:
這兩種傳輸協議也就是合於適配不同的業務和不同的硬件終端。
在使用中,類似於圖像、聲音等對可靠性要求沒有那麼高的業務可以用UDP,他們不需要準確存儲對準確性無要求但要求速度快。
類似於文本、程序、文件等要求可靠的數據最好就用TCP,但會犧牲一些速度。
對系統資源的要求:CP較多,UDP少。
程序結構:UDP程序結構較簡單,TCP複雜。
流模式與數據報模式:TCP保證數據正確性,UDP可能丟包; TCP保證數據順序,UDP不保證
二.用途
TCP是面向連接的,有比較高的可靠性,一些要求比較高的服務一般使用這個協議,如FTP、Telnet、SMTP、HTTP、POP3等,而UDP是面向無連接的,使用這個協議的常見服務有DNS、SNMP、QQ等。對於QQ必須另外說明一下,QQ2003以前是隻使用UDP協議的,其服務器使用8000端口,偵聽是否有信息傳來,客戶端使用4000端口,向外發送信息(這也就不難理解在一般的顯IP的QQ版本中顯示好友的IP地址信息中端口常爲4000或其後續端口的原因了),即QQ程序既接受服務又提供服務,在以後的QQ版本中也支持使用TCP協議了。
Udp是一種面向無連接的通信協議,該協議使得數據傳輸的速度得到大幅度的提高。視頻聊天語音聊天基本都是用UPD協議。
三.例子
TCP: ServerSocket ss = new ServerSocket(2000);
UDP: 創建DatagramSocket對象,DatagramSocket區別於Tcp方式下的socket對象。
DatagramSocket ds=new DatagramSocket();
下面是具體的程序代碼,已經編譯通過,另外附件也是源碼可以直接下載。
TCP服務器端
- package com.zakisoft.tcp;
- import java.io.InputStreamReader;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class TCPServer {
- public static void main(String[] args) throws Exception {
- ServerSocket ss = new ServerSocket(2000);
- while (true) {
- Socket s = ss.accept();
- System.out.println("A client has heen connected.");
- InputStreamReader r = new InputStreamReader(s.getInputStream());
- int c = 0;
- while ((c = r.read()) > -1) {
- System.out.print((char) c);
- }
- System.out.println();
- r.close();
- s.close();
- }
- }
- }
TCP客戶端
- package com.zakisoft.tcp;
- import java.io.OutputStreamWriter;
- import java.net.Socket;
- public class TCPClient {
- public static void main(String[] args) throws Exception {
- Socket s = new Socket("127.0.0.1", 2000);
- OutputStreamWriter w = new OutputStreamWriter(s.getOutputStream());
- w.write("Hello服務器");
- w.flush();
- w.close();
- s.close();
- }
- }
------------------------------------------------------------
UDP服務器端
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- import java.net.InetSocketAddress;
- import java.net.SocketException;
- /**
- * UDP服務類
- */
- public class UdpServerSocket {
- private byte[] buffer = new byte[1024];
- private DatagramSocket ds = null;
- private DatagramPacket packet = null;
- private InetSocketAddress socketAddress = null;
- private String orgIp;
- /**
- * 構造函數,綁定主機和端口.
- *
- * @param host
- * 主機
- * @param port
- * 端口
- * @throws Exception
- */
- public UdpServerSocket(String host, int port) throws Exception {
- socketAddress = new InetSocketAddress(host, port);
- ds = new DatagramSocket(socketAddress);
- System.out.println("服務端啓動!");
- }
- public final String getOrgIp() {
- return orgIp;
- }
- /**
- * 設置超時時間,該方法必須在bind方法之後使用.
- *
- * @param timeout
- * 超時時間
- * @throws Exception
- */
- public final void setSoTimeout(int timeout) throws Exception {
- ds.setSoTimeout(timeout);
- }
- /**
- * 獲得超時時間.
- *
- * @return 返回超時時間.
- * @throws Exception
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:34:36
- */
- public final int getSoTimeout() throws Exception {
- return ds.getSoTimeout();
- }
- /**
- * 綁定監聽地址和端口.
- *
- * @param host
- * 主機IP
- * @param port
- * 端口
- * @throws SocketException
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:36:17
- */
- public final void bind(String host, int port) throws SocketException {
- socketAddress = new InetSocketAddress(host, port);
- ds = new DatagramSocket(socketAddress);
- }
- /**
- * 接收數據包,該方法會造成線程阻塞.
- *
- * @return 返回接收的數據串信息
- * @throws IOException
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:38:24
- */
- public final String receive() throws IOException {
- packet = new DatagramPacket(buffer, buffer.length);
- ds.receive(packet);
- orgIp = packet.getAddress().getHostAddress();
- String info = new String(packet.getData(), 0, packet.getLength());
- System.out.println("接收信息:" + info);
- return info;
- }
- /**
- * 將響應包發送給請求端.
- *
- * @param bytes
- * 迴應報文
- * @throws IOException
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午11:05:31
- */
- public final void response(String info) throws IOException {
- System.out.println("客戶端地址 : " + packet.getAddress().getHostAddress()
- + ",端口:" + packet.getPort());
- DatagramPacket dp = new DatagramPacket(buffer, buffer.length, packet
- .getAddress(), packet.getPort());
- dp.setData(info.getBytes());
- ds.send(dp);
- }
- /**
- * 設置報文的緩衝長度.
- *
- * @param bufsize
- * 緩衝長度
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:47:49
- */
- public final void setLength(int bufsize) {
- packet.setLength(bufsize);
- }
- /**
- * 獲得發送迴應的IP地址.
- *
- * @return 返回迴應的IP地址
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:48:27
- */
- public final InetAddress getResponseAddress() {
- return packet.getAddress();
- }
- /**
- * 獲得迴應的主機的端口.
- *
- * @return 返回迴應的主機的端口.
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:48:56
- */
- public final int getResponsePort() {
- return packet.getPort();
- }
- /**
- * 關閉udp監聽口.
- *
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:49:23
- */
- public final void close() {
- try {
- ds.close();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- /**
- * 測試方法.
- *
- * @param args
- * @throws Exception
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:49:50
- */
- public static void main(String[] args) throws Exception {
- String serverHost = "127.0.0.1";
- int serverPort = 3366;
- UdpServerSocket udpServerSocket = new UdpServerSocket(serverHost,
- serverPort);
- while (true) {
- udpServerSocket.receive();
- udpServerSocket.response("你好,KuToKu.com!");
- }
- }
- }
UDP客戶端
- package com.zakisoft.upd;
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- /**
- * UDP客戶端程序,用於對服務端發送數據,並接收服務端的迴應信息.
- */
- public class UdpClientSocket {
- private byte[] buffer = new byte[1024];
- private DatagramSocket ds = null;
- /**
- * 構造函數,創建UDP客戶端
- *
- * @throws Exception
- */
- public UdpClientSocket() throws Exception {
- ds = new DatagramSocket();
- }
- /**
- * 設置超時時間,該方法必須在bind方法之後使用.
- *
- * @param timeout
- * 超時時間
- * @throws Exception
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:55:12
- */
- public final void setSoTimeout(final int timeout) throws Exception {
- ds.setSoTimeout(timeout);
- }
- /**
- * 獲得超時時間.
- *
- * @return 返回超時時間
- * @throws Exception
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:55:25
- */
- public final int getSoTimeout() throws Exception {
- return ds.getSoTimeout();
- }
- public final DatagramSocket getSocket() {
- return ds;
- }
- /**
- * 向指定的服務端發送數據信息.
- *
- * @param host
- * 服務器主機地址
- * @param port
- * 服務端端口
- * @param bytes
- * 發送的數據信息
- * @return 返回構造後俄數據報
- * @throws IOException
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午11:02:41
- */
- public final DatagramPacket send(final String host, final int port,
- final byte[] bytes) throws IOException {
- DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress
- .getByName(host), port);
- ds.send(dp);
- return dp;
- }
- /**
- * 接收從指定的服務端發回的數據.
- *
- * @param lhost
- * 服務端主機
- * @param lport
- * 服務端端口
- * @return 返回從指定的服務端發回的數據.
- * @throws Exception
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:52:36
- */
- public final String receive(final String lhost, final int lport)
- throws Exception {
- DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
- ds.receive(dp);
- String info = new String(dp.getData(), 0, dp.getLength());
- return info;
- }
- /**
- * 關閉udp連接.
- *
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午10:53:52
- */
- public final void close() {
- try {
- ds.close();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- /**
- * 測試客戶端發包和接收回應信息的方法.
- *
- * @param args
- * @throws Exception
- * @author <a href="mailto:[email protected]">KuToKu.com</a> Creation date:
- * 2007-8-16 - 下午11:03:54
- */
- public static void main(String[] args) throws Exception {
- UdpClientSocket client = new UdpClientSocket();
- String serverHost = "127.0.0.1";
- int serverPort = 3366;
- client.send(serverHost, serverPort, ("你好!").getBytes());
- String info = client.receive(serverHost, serverPort);
- System.out.println("服務端迴應數據:" + info);
- }
- }
更多TCP和UPD的資料:
TCP---傳輸控制協議,提供的是面向連接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間建立一個TCP連接,之後才能傳輸數 據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。
UDP---用戶數據報協議,是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,但是並不能保證它 們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快。
UDP 與 TCP 的主要區別在於 UDP 不一定提供可靠的數據傳輸。事實上,該協議不能保證數據準確無誤地到達目的地。UDP 在許多方面非常有效。當某個程序的目標是儘快地傳輸儘可能多的信息時(其中任意給定數據的重要性相對較低),可使用 UDP。ICQ 短消息使用 UDP 協議發送消息。
許多程序將使用單獨的TCP連接和單獨的UDP連接。重要的狀態信息隨可靠的TCP連接發送,而主數據流通過UDP發送。
TCP的目的是提供可靠的數據傳輸,並在相互進行通信的設備或服務之間保持一個虛擬連接。TCP在數據包接收無序、丟失或在交付期間被破壞時,負責數據恢 復。它通過爲其發送的每個數據包提供一個序號來完成此恢復。記住,較低的網絡層會將每個數據包視爲一個獨立的單元,因此,數據包可以沿完全不同的路徑發 送,即使它們都是同一消息的組成部分。這種路由與網絡層處理分段和重新組裝數據包的方式非常相似,只是級別更高而已。
爲確保正確地接收數據,TCP要求在目標計算機成功收到數據時發回一個確認(即 ACK)。如果在某個時限內未收到相應的 ACK,將重新傳送數據包。如果網絡擁塞,這種重新傳送將導致發送的數據包重複。但是,接收計算機可使用數據包的序號來確定它是否爲重複數據包,並在必要 時丟棄它。
TCP與UDP的選擇
如果比較UDP包和TCP包的結構,很明顯UDP包不具備TCP包複雜的可靠性與控制機制。與TCP協議相同,UDP的源端口數和目的端口數也都支持一臺 主機上的多個應用。一個16位的UDP包包含了一個字節長的頭部和數據的長度,校驗碼域使其可以進行整體校驗。(許多應用只支持UDP,如:多媒體數據 流,不產生任何額外的數據,即使知道有破壞的包也不進行重發。)
很明顯,當數據傳輸的性能必須讓位於數據傳輸的完整性、可控制性和可靠性時,TCP協議是當然的選擇。當強調傳輸性能而不是傳輸的完整性時,如:音頻和多 媒體應用,UDP是最好的選擇。在數據傳輸時間很短,以至於此前的連接過程成爲整個流量主體的情況下,UDP也是一個好的選擇,如:DNS交換。把 SNMP建立在UDP上的部分原因是設計者認爲當發生網絡阻塞時,UDP較低的開銷使其有更好的機會去傳送管理數據。TCP豐富的功能有時會導致不可預料 的性能低下,但是我們相信在不遠的將來,TCP可靠的點對點連接將會用於絕大多數的網絡應用。
FTP協議即文件傳輸協議,它是一個標準協議,FTP協議也是應用TCP/IP協議的應用協議標準,它是在計算機和網絡之間交換文件的最簡單的方法。