Socket
所謂套接字(Socket),就是對網絡中不同主機上的應用進程之間進行雙向通信的端點的抽象。一個套接字就是網絡上進程通信的一端
利用套接字(Socket)開發網絡應用程序早已被廣泛的采用,以至於成為事實 上的標准。
網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的標 識符套接字。
通信的兩端都要有Socket,是兩台機器間通信的端點。
網絡通信其實就是Socket間的通信。
Socket允許程序把網絡連接當成一個流,數據在兩個Socket間通過IO傳輸。
一般主動發起通信的應用程序屬客戶端,等待通信請求的為服務端。
Socket的分類
流套接字(stream socket): 使用TCP提供可依賴的字節流服務
數據報套接字(datagram socket): 使用UDP提供“盡力而為”的數據報服務
Socket的操作
Socket類的常用構造器: public Socket(InetAddress address,int port)創建一個流套接字並將其連接到指定 IP 地址的指定端口號。 public Socket(String host,int port)創建一個流套接字並將其連接到指定主機上的指定端口號。 Socket類的常用方法: public InputStream getInputStream()返回此套接字的輸入流。可以用於接收網絡消息 public OutputStream getOutputStream()返回此套接字的輸出流。可以用於發送網絡消息 public InetAddress getInetAddress()此套接字連接到的遠程 IP 地址;如果套接字是未連接的,則返回 null。 public InetAddress getLocalAddress()獲取套接字綁定的本地地址。 即本端的IP地址 public int getPort()此套接字連接到的遠程端口號;如果尚未連接套接字,則返回 0。 public int getLocalPort()返回此套接字綁定到的本地端口。 如果尚未綁定套接字,則返回 -1。即本端的 端口號。 public void close()關閉此套接字。套接字被關閉后,便不可在以后的網絡連接中使用(即無法重新連接 或重新綁定)。需要創建新的套接字對象。 關閉此套接字也將會關閉該套接字的 InputStream 和 OutputStream。 public void shutdownInput()如果在套接字上調用 shutdownInput() 后從套接字輸入流讀取內容,則流將 返回 EOF(文件結束符)。 即不能在從此套接字的輸入流中接收任何數據。 public void shutdownOutput()禁用此套接字的輸出流。對於 TCP 套接字,任何以前寫入的數據都將被發 送,並且后跟 TCP 的正常連接終止序列。 如果在套接字上調用 shutdownOutput() 后寫入套接字輸出流, 則該流將拋出 IOException。 即不能通過此套接字的輸出流發送任何數據。
基於Socket的Tcp編程
Java語言的基於套接字編程分為服務端編程和客戶端編程,其通信模 型如圖所示:
客戶端Socket的工作過程包含以下四個基本的步驟:
創建 Socket:根據指定服務端的 IP 地址或端口號構造 Socket 類對象。若服務器端 響應,則建立客戶端到服務器的通信線路。若連接失敗,會出現異常。 打開連接到 Socket 的輸入/出流: 使用 getInputStream()方法獲得輸入流,使用 getOutputStream()方法獲得輸出流,進行數據傳輸 按照一定的協議對Socket 進行讀/寫操作:通過輸入流讀取服務器放入線路的信息 (但不能讀取自己放入線路的信息),通過輸出流將信息寫入線程。 關閉 Socket:斷開客戶端到服務器的連接,釋放線路
客戶端程序可以使用Socket類創建對象,創建的同時會自動向服務器方發起連 接。Socket的構造器是: Socket(String host,int port)throws UnknownHostException,IOException:向服務器(域名是 host。端口號為port)發起TCP連接,若成功,則創建Socket對象,否則拋出異常。 Socket(InetAddress address,int port)throws IOException:根據InetAddress對象所表示的 IP地址以及端口號port發起連接。 客戶端建立socketAtClient對象的過程就是向服務器發出套接字連接請求 Socket s = new Socket(“192.168.40.165”,9999); OutputStream out = s.getOutputStream(); out.write(" hello".getBytes()); s.close();
指定服務端ip和端口的時候可以使用new Socket(ip,端口)也可以借助InetAddress來完成
/** * 實現TCP的網絡編程 * * 例子1:客戶端發送信息給服務端,服務端將數據顯示在控制台上 * @param args */ public static void main(String[] args) { Socket socket = null; // 使用socket建立服務端 OutputStream os = null; try { //1 創建Socket對象指明 服務端ip和端口 InetAddress inetAddress = InetAddress.getByName("192.168.1.10"); // 指定服務端的ip地址 socket = new Socket(inetAddress,8899); // 2 : socket獲取一個輸出流 用於輸出數據 os = socket.getOutputStream(); // 3 :寫出數據 os.write("老王我是客戶端來請求你".getBytes()); } catch (IOException e) { e.printStackTrace(); //4 :資源的關閉, 關閉流和socket } finally { if(os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
服務端Socket的工作過程包含以下四個基本的步驟:
調用 ServerSocket(int port) :創建一個服務器端套接字,並綁定到指定端口 上。用於監聽客戶端的請求。 調用 accept():監聽連接請求,如果客戶端請求連接,則接受連接,返回通信 套接字對象。 調用 該Socket類對象的 getOutputStream() 和 getInputStream ():獲取輸出 流和輸入流,開始網絡數據的發送和接收。 關閉ServerSocket和Socket對象:客戶端訪問結束,關閉通信套接字。
服務器建立 ServerSocket 對象
ServerSocket 對象負責等待客戶端請求建立套接字連接,類似郵局某個窗口 中的業務員。也就是說,服務器必須事先建立一個等待客戶請求建立套接字 連接的ServerSocket對象。 所謂“接收”客戶的套接字請求,就是accept()方法會返回一個 Socket 對象 ServerSocket ss = new ServerSocket(9999); Socket s = ss.accept (); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int num = in.read(buf); String str = new String(buf,0,num); System.out.println(s.getInetAddress().toString()+”:”+str); s.close(); ss.close();
server端取數據盡量使用ByteArrayOutputStream因為它會在內部建立一個緩沖區先將數據存儲到緩沖區,等數據獲取完畢一次輸出,不會因為外部建的數組不夠大導致數據亂碼
public class TcpTestOneServer { public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; InputStream is = null; ByteArrayOutputStream bo = null; try { // 1.創建服務器端的ServerSocket,指明自己的端口號 serverSocket = new ServerSocket(8899); // 2.調用accept()表示接收來自於客戶端的socket socket = serverSocket.accept(); // 獲取輸入流 is = socket.getInputStream(); /* 這樣寫有可能亂碼 : 輸出結果 老王我是客戶��來請求你 byte [] bytes = new byte[20]; int len; while ((len = is.read(bytes)) != -1){ String str = new String(bytes,0,len); System.out.print(str); } */ bo = new ByteArrayOutputStream(); byte [] buffer = new byte[5]; int len; while ((len = is.read(buffer)) != -1){ bo.write(buffer,0,len); } System.out.println(bo.toString()); System.out.println("/接收到了 來自"+socket.getInetAddress().getHostAddress()+"的數據"); } catch (IOException e) { e.printStackTrace(); } finally { if(serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(bo != null){ try { bo.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Socket通信的理解
socket通信好比你去郵局寄快遞,socket就是郵局,個人是client端,server是你的郵寄對象(your feriends),
client在郵寄的時候先要獲取到server的地址,也就是ip和端口就好比你朋友的小區和門牌號,
這樣才能精准的找到目標,然后將要寫的數據通過郵局,也就是輸出流郵局socket將你要寫的數據通過OutputStream信封把數據存儲起來,然后發送,你要發送的數據都存儲在郵局的信封內:Socket.OutputStream()中.
Server你的朋友在收取數據的時候要先在家等着才能收到信封,所以將朋友在家的狀態設為ServerSocket,朋友除了在家還要同意接受信封而不是拒收,所以朋友同意的狀態是基於在家的前提那就是
serverSocket.accept();那么就可以將信封給你了拿到信封 Socket.InputStream(),然后就是拆信封ByteArrayOutputStream()讀取數據
在傳輸數據的時候 服務端在接收數據使用read()的時候,會進行阻塞,因為client端沒有傳遞給一個確切的斷開連接的信息,所以client在使用socket傳輸數據的時候不僅僅要關閉socket還要告訴
server端什么時候數據傳輸完畢要關閉連接 使用socket.shutdownOutput()關閉輸出,不然server端還在等着你的傳輸不會進行下面的步驟server會卡住
Tcp-Practices
客戶端發送文件給服務端,服務端將文件保存在本地。
client

public static void main(String[] args) { Socket socket = null; OutputStream osSix = null; FileInputStream fileInputStream = null; try { socket = new Socket("192.168.1.10",1005); osSix = socket.getOutputStream(); fileInputStream = new FileInputStream(new File("beauty.jpg")); // 操作文件用到字節流來 byte [] bytes = new byte[1024]; int len; while ((len = fileInputStream.read(bytes)) != -1){ osSix.write(bytes,0,len); } socket.shutdownOutput(); } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(osSix != null){ try { osSix.close(); } catch (IOException e) { e.printStackTrace(); } } if(fileInputStream != null){ try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
server

public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; InputStream is = null; FileOutputStream fw = null; try { serverSocket = new ServerSocket(1005); socket = serverSocket.accept(); is = socket.getInputStream(); fw = new FileOutputStream("beautyThree.jpg"); byte [] bytes = new byte[1024]; int len; while ((len = is.read(bytes)) != -1){ fw.write(bytes,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if(serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(fw != null){ try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2:從客戶端發送文件給服務端,服務端保存到本地。並返回“發送成功”給客戶端。

/* 這里涉及到的異常,應該使用try-catch-finally處理 */ @Test public void client() throws IOException { //1. Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090); //2. OutputStream os = socket.getOutputStream(); //3. FileInputStream fis = new FileInputStream(new File("beauty.jpg")); //4. byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1){ os.write(buffer,0,len); } //關閉數據的輸出 socket.shutdownOutput(); //5.接收來自於服務器端的數據,並顯示到控制台上 InputStream is = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bufferr = new byte[20]; int len1; while((len1 = is.read(buffer)) != -1){ baos.write(buffer,0,len1); } System.out.println(baos.toString()); //6. fis.close(); os.close(); socket.close(); baos.close(); } /* 這里涉及到的異常,應該使用try-catch-finally處理 */ @Test public void server() throws IOException { //1. ServerSocket ss = new ServerSocket(9090); //2. Socket socket = ss.accept(); //3. InputStream is = socket.getInputStream(); //4. FileOutputStream fos = new FileOutputStream(new File("beauty2.jpg")); //5. byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer)) != -1){ fos.write(buffer,0,len); } System.out.println("圖片傳輸完成"); //6.服務器端給予客戶端反饋 OutputStream os = socket.getOutputStream(); os.write("你好,美女,照片我已收到,非常漂亮!".getBytes()); //7. fos.close(); is.close(); socket.close(); ss.close(); os.close(); }
這里涉及交互的問題需要用到socket.shutdownOutput() 來通知對方已經傳遞完數據
3: .服務端讀取圖片並發送給客戶端,客戶端保存圖片到本地

@Test public void TcpTestThreeClient(){ Socket socket = null; InputStream is = null; FileOutputStream fos = null; try { socket = new Socket("127.0.0.1",1002); is = socket.getInputStream(); fos = new FileOutputStream("aTcp.jpg"); int len; byte [] bytes = new byte[1024]; while ((len = is.read(bytes)) != -1){ fos.write(bytes,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(fos != null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void TcpTestThreeServer(){ ServerSocket serverSocketThree = null; Socket socketThree = null; OutputStream os = null; FileInputStream fis = null; try { serverSocketThree = new ServerSocket(1002); socketThree = serverSocketThree.accept(); os = socketThree.getOutputStream(); fis = new FileInputStream("a.jpg"); int len; byte [] bytes = new byte[1024]; while ((len = fis.read(bytes)) != -1){ os.write(bytes,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if(serverSocketThree != null){ try { serverSocketThree.close(); } catch (IOException e) { e.printStackTrace(); } } if(os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if(socketThree != null){ try { socketThree.close(); } catch (IOException e) { e.printStackTrace(); } } } }
4: .客戶端給服務端發送文本,服務端會將文本轉成大寫在返回給客戶端。

@Test public void TcpTestFourClient(){ Socket socket = null; OutputStream os = null; InputStream is = null; ByteArrayOutputStream bos = null; try { socket = new Socket("127.0.0.1",1003); os = socket.getOutputStream(); os.write("I'm laowang".getBytes()); socket.shutdownOutput(); // 關閉數據類的輸出不然server.read()會一直阻塞等待接受數據,因為你下面還在等待接受數據並沒有關閉socket server會誤認為你還要發送 is = socket.getInputStream(); int len; byte [] bytes = new byte[5]; bos = new ByteArrayOutputStream(); while ((len = is.read(bytes)) != -1){ bos.write(bytes,0,len); } System.out.println(bos.toString()); } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(bos != null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void TcpTestFourServer(){ ServerSocket serverSocket = null; Socket socket = null; InputStream is= null; OutputStream os = null; ByteArrayOutputStream bos = null; try { serverSocket = new ServerSocket(1003); socket = serverSocket.accept(); is = socket.getInputStream(); os = socket.getOutputStream(); bos = new ByteArrayOutputStream(); int len; byte [] bytes = new byte[5]; while ((len = is.read(bytes)) != -1){ bos.write(bytes,0,len); } System.out.println("接到了來組客戶端的信息"); String str = bos.toString().toUpperCase(); System.out.println(str); os.write(str.getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if(serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(bos !=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
UDP網絡通信
類 DatagramSocket 和 DatagramPacket 實現了基於 UDP 協議網絡程序
UDP數據報通過數據報套接字 DatagramSocket 發送和接收,系統不保證 UDP數據報一定能夠安全送到目的地,也不能確定什么時候可以抵達。
DatagramPacket 對象封裝了UDP數據報,在數據報中包含了發送端的IP 地址和端口號以及接收端的IP地址和端口號。
UDP協議中每個數據報都給出了完整的地址信息,因此無須建立發送方和 接收方的連接。如同發快遞包裹一樣
可以理解為udp為了追求效率不在乎對方是否收到 只發送自己所需要發送的內容
DatagramSocket 類的常用方法
public DatagramSocket(int port)創建數據報套接字並將其綁定到本地主機上的指定端口。套接字將被 綁定到通配符地址,IP 地址由內核來選擇。 public DatagramSocket(int port,InetAddress laddr)創建數據報套接字,將其綁定到指定的本地地址。 本地端口必須在 0 到 65535 之間(包括兩者)。如果 IP 地址為 0.0.0.0,套接字將被綁定到通配符地 址,IP 地址由內核選擇。 public void close()關閉此數據報套接字。 public void send(DatagramPacket p)從此套接字發送數據報包。DatagramPacket 包含的信息指示:將 要發送的數據、其長度、遠程主機的IP 地址和遠程主機的端口號。 public void receive(DatagramPacket p)從此套接字接收數據報包。當此方法返回時,DatagramPacket 的緩沖區填充了接收的數據。數據報包也包含發送方的 IP 地址和發送方機器上的端口號。 此方法 在接收到數據報前一直阻塞。數據報包對象的 length 字段包含所接收信息的長度。如果信息比包的 長度長,該信息將被截短。 public InetAddress getLocalAddress()獲取套接字綁定的本地地址。 public int getLocalPort()返回此套接字綁定的本地主機上的端口號。 public InetAddress getInetAddress()返回此套接字連接的地址。如果套接字未連接,則返回null。 public int getPort()返回此套接字的端口。如果套接字未連接,則返回-1。
public DatagramPacket(byte[] buf,int length)構造 DatagramPacket,用來接收長 度為 length 的數據包。 length 參數必須小於等於 buf.length。
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)構造數 據報包,用來將長度為 length 的包發送到指定主機上的指定端口號。length 參數必須小於等於 buf.length。
public InetAddress getAddress()返回某台機器的 IP 地址,此數據報將要發往該 機器或者是從該機器接收到的。
public int getPort()返回某台遠程主機的端口號,此數據報將要發往該主機或 者是從該主機接收到的。
public byte[] getData()返回數據緩沖區。接收到的或將要發送的數據從緩沖區 中的偏移量 offset 處開始,持續 length 長度。
public int getLength()返回將要發送或接收到的數據的長度。
UDP網絡通信
流 程:
1. DatagramSocket與DatagramPacket
2. 建立發送端,接收端
3. 建立數據包
4. 調用Socket的發送、接收方法
5. 關閉Socket
發送端與接收端是兩個獨立的運行程序
udp通信
@Test public void UdpTestOneClient(){ DatagramSocket socket = null; try { socket = new DatagramSocket(); byte [] data = "我是要傳遞的客戶端".getBytes(); InetAddress ia = InetAddress.getLocalHost(); DatagramPacket packet = new DatagramPacket(data,0,data.length,ia,1001); socket.send(packet); } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ socket.close(); } } } @Test public void UdpTestOneServer(){ DatagramSocket socket = null; try { socket = new DatagramSocket(1001); byte [] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length); socket.receive(packet); System.out.println(new String(packet.getData(),0,packet.getLength())); } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ try { socket.close(); } catch (Exception e) { e.printStackTrace(); } } } }
URL類
URL(Uniform Resource Locator):統一資源定位符,它表示 Internet 上某一 資源的地址 它是一種具體的URI,即URL可以用來標識一個資源,而且還指明了如何locate 這個資源。 通過 URL 我們可以訪問 Internet 上的各種網絡資源,比如最常見的 www,ftp 站點。瀏覽器通過解析給定的 URL 可以在網絡上查找相應的文件或其他資源。 URL的基本結構由5部分組成: <傳輸協議>://<主機名>:<端口號>/<文件名>#片段名?參數列表 例如: http://192.168.1.100:8080/helloworld/index.jsp#a?username=shkstart&password=123 #片段名:即錨點,例如看小說,直接定位到章節 參數列表格式:參數名=參數值&參數名=參數值....
URL類構造器
為了表示URL,java.net 中實現了類 URL。我們可以通過下面的構造器來初 始化一個 URL 對象: public URL (String spec):通過一個表示URL地址的字符串可以構造一個URL對象。例 如:URL url = new URL ("http://www. atguigu.com/"); public URL(URL context, String spec):通過基 URL 和相對 URL 構造一個 URL 對象。 例如:URL downloadUrl = new URL(url, “download.html") public URL(String protocol, String host, String file); 例如:new URL("http", "www.atguigu.com", “download. html"); public URL(String protocol, String host, int port, String file); 例如: URL gamelan = new URL("http", "www.atguigu.com", 80, “download.html"); URL類的構造器都聲明拋出非運行時異常,必須要對這一異常進行處理,通 常是用 try-catch 語句進行捕獲。
URL類常用方法
一個URL對象生成后,其屬性是不能被改變的,但可以通過它給定的 方法來獲取這些屬性: public String getProtocol( ) 獲取該URL的協議名 public String getHost( ) 獲取該URL的主機名 public String getPort( ) 獲取該URL的端口號 public String getPath( ) 獲取該URL的文件路徑 public String getFile( ) 獲取該URL的文件名 public String getQuery( ) 獲取該URL的查詢名
URL url = new URL("http://localhost:8080/examples/beauty.jpg?username=Tom"); // public String getProtocol( ) 獲取該URL的協議名 System.out.println(url.getProtocol()); // public String getHost( ) 獲取該URL的主機名 System.out.println(url.getHost()); // public String getPort( ) 獲取該URL的端口號 System.out.println(url.getPort()); // public String getPath( ) 獲取該URL的文件路徑 System.out.println(url.getPath()); // public String getFile( ) 獲取該URL的文件名 System.out.println(url.getFile()); // public String getQuery( ) 獲取該URL的查詢名 System.out.println(url.getQuery());
URLConnection類
URL的方法 openStream():能從網絡上讀取數據 若希望輸出數據,例如向服務器端的 CGI (公共網關接口-Common Gateway Interface-的簡稱,是用戶瀏覽器和服務器端的應用程序進行連接的接口)程序發送一 些數據,
則必須先與URL建立連接,然后才能對其進行讀寫,此時需要使用 URLConnection 。 URLConnection:表示到URL所引用的遠程對象的連接。當與一個URL建立連接時, 首先要在一個 URL 對象上通過方法 openConnection() 生成對應的 URLConnection 對象。如果連接過程失敗,將產生IOException. URL netchinaren = new URL ("http://www.atguigu.com/index.shtml"); URLConnectonn u = netchinaren.openConnection( );
Summarize
位於網絡中的計算機具有唯一的IP地址,這樣不同的主機可以互相區分。
客戶端-服務器是一種最常見的網絡應用程序模型。服務器是一個為其客戶端提供某種特定 服務的硬件或軟件。
客戶機是一個用戶應用程序,用於訪問某台服務器提供的服務。端口號 是對一個服務的訪問場所,它用於區分同一物理計算機上的多個服務。
套接字用於連接客戶 端和服務器,客戶端和服務器之間的每個通信會話使用一個不同的套接字。TCP協議用於實 現面向連接的會話。
Java 中有關網絡方面的功能都定義在 java.net 程序包中。Java 用 InetAddress 對象表示 IP 地址,該對象里有兩個字段:主機名(String) 和 IP 地址(int)。
類 Socket 和 ServerSocket 實現了基於TCP協議的客戶端-服務器程序。Socket是客戶端 和服務器之間的一個連接,連接創建的細節被隱藏了。
這個連接提供了一個安全的數據傳輸 通道,這是因為 TCP 協議可以解決數據在傳送過程中的丟失、損壞、重復、亂序以及網絡 擁擠等問題,它保證數據可靠的傳送。
類 URL 和 URLConnection 提供了最高級網絡應用。URL 的網絡資源的位置來同一表示 Internet 上各種網絡資源。通過URL對象可以創建當前應用程序和 URL 表示的網絡資源之 間的連接,
這樣當前程序就可以讀取網絡資源數據,或者把自己的數據傳送到網絡上去。
。