詳解Socket接口

原文地址:詳解Socket接口作者:於士博
要學Internet上的TCP/IP網絡編程,必須深刻理解Socket接口。之所以另起一篇文章來討論Socket,是因爲它是網絡通信架構的基礎,重要性不言而喻。所謂socket通常也稱作“套接字”,用於描述IP地址和端口,是一個通信鏈的句柄。應用程序通常通過“套接字”向網絡發出請求或者應答網絡請求。socket的英文原義是“孔”或“插座”。在這裏作爲通信機制,取後者意思。socket非常類似於電話插座。以一個國家級電話網爲例。電話的通話雙方相當於相互通信的2個進程,區號是它的網絡地址;區內一個單位的交換機相當於一臺主機,主機分配給每個用戶的局內號碼相當於socket號(JAVA程序的socket ID 由操作系統分配)。任何用戶在通話之前,首先要佔有一部電話機,相當於申請一個socket;同時要知道對方的號碼,相當於對方有一個固定的socket。然後向對方撥號呼叫,相當於發出連接請求(假如對方不在同一區內,還要撥對方區號,相當於給出網絡地址)。對方假如在場並空閒(相當於通信的另一主機開機且可以接受連接請求),拿起電話話筒,雙方就可以正式通話,相當於連接成功。雙方通話的過程,是一方向電話機發出信號和對方從電話機接收信號的過程,相當於向socket發送數據和從socket接收數據。通話結束後,一方掛起電話機相當於關閉socket,撤消連接。

       在電話系統中,一般用戶只能感受到本地電話機和對方電話號碼的存在,建立通話的過程,話音傳輸的過程以及整個電話系統的技術細節對他都是透明的,這也與socket機制非常相似。socket利用網間網通信設施實現進程通信,但它對通信設施的細節毫不關心,只要通信設施能提供足夠的通信能力,它就滿足了。

      至此,我們對socket進行了直觀的描述。抽象出來,socket實質上提供了進程通信的端點。進程通信之前,雙方首先必須各自創建一個端點,否則是沒有辦法建立聯繫並相互通信的。正如打電話之前,雙方必須各自擁有一臺電話機一樣。在網間網內部,每一個socket用一個結構體相關描述:
  (協議,本地地址,本地端口) 一個完整的socket有一個本地唯一的socket號

      最重要的是,socket 是面向客戶/服務器模型而設計的,針對客戶和服務器程序提供不同的socket 系統調用。客戶隨機申請一個socket (相當於一個想打電話的人可以在任何一臺入網電話上撥號呼叫),系統爲之分配一個socket號;服務器擁有全局公認的 socket ,任何客戶都可以向它發出連接請求和信息請求(相當於一個被呼叫的電話擁有一個呼叫方知道的電話號碼)。

      socket利用客戶/服務器模式巧妙地解決了進程之間建立通信連接的問題。服務器socket 半相關爲全局所公認非常重要。一般來說,編好程序 > 訪問,調用,數據填充,邏輯組織 > socket組件 > 操作系統的通信API > 到達網線出口。這樣就可以實現與外部的連接。

        實際上在 Java 開發中大家已經不知不覺地用到了 Socket,只不過不是你實現的。比如:JDBC 數據庫廠商的實現、Tomcat 作爲一個簡單的 Web 服務器也是需要使用 Socket 實現 HTTP 通信的。Socket 通信是所有通信交互方式中最快的,但是在代碼編寫上也是最麻煩的,特別是非阻塞的 Socket 通信。Socket 僅僅是 J2SE 中的東西,但是相比較於 J2EE 中的其他東西來說也是很麻煩的,需要設計和編寫者擁有一定的通信基本知識,以及多線程併發編程的知識。

     Java 是以網絡、安全和線程處理著稱的,因此在這些方面都有很強大的優勢,有着豐富的 API:在網絡通信方面,有 TCP 通信的 Socket,UDP 通信的 DatagramSocket,以及與 SSL 相關 JSSE 中的LSocket,以及這些非阻塞的 SocketChannel, DatagramChannel, SSLEngine在安全方面,JCA, JCE, JAAS 等等,線程處理方面,從 JDK 5 開始增加了 java.util.concurrent 這個包,添加了很多控制多線程併發的 API,對上面這些 J2SE 中 API 的應用熟悉的話,那可以說在 Java 層面上有了更進一步的瞭解。當然對於本人來說,一切還剛剛起步。

  Socket 接口是訪問 Internet 使用得最廣泛的方法。 如果你有一臺剛配好TCP/IP協議的主機,其IP地址是202.120.127.201, 此時在另一臺主機或同一臺主機上執行ftp 202.120.127.201,顯然無法建立連接。因"202.120.127.201" 這臺主機沒有運行FTP服務軟件。同樣, 在另一臺或同一臺主機上運行瀏覽軟件 如Netscape,輸入"http://202.120.127.201",也無法建立連接。現在,如果在這臺主機上運行一個FTP服務軟件(該軟件將打開一個Socket, 並將其綁定到21端口),再在這臺主機上運行一個Web 服務軟件(該軟件將打開另一個Socket,並將其綁定到80端口)。這樣,在另一臺主機或同一臺主機上執行ftp 202.120.127.201,FTP客戶軟件將通過21端口來呼叫主機上由FTP 服務軟件提供的Socket,與其建立連接並對話。而在netscape中輸入"http://202.120.127.201"時,將通過80端口來呼叫主機上由Web服務軟件提供的Socket,與其建 立連接並對話。

  在Internet上有很多這樣的主機,這些主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務。Socket正如其英文原意那樣,象一個多孔插座。一臺主機猶如佈滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟件將插頭插到不同編號的插座,就可以得到不同的服務。

  Socket和ServerSocket類庫位於java.net包中。ServerSocket用於服務器端,Socket是建立網絡連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話。對於一個網絡連接來說,套接字是平等的,並沒有差別,不因爲在服務器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。

  Accept方法用於產生"阻塞",直到接受到一個連接,並且返回一個客戶端的Socket對象實例。"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,然後程序繼續;通常"阻塞"是由循環產生的。getInputStream方法獲得網絡連接輸入,同時返回一個InputStream對象實例。getOutputStream方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。 注意:其中getInputStream和getOutputStream方法均可能會產生一個IOException,它必須被捕獲,因爲它們返回的流對象,通常都會被另一個流對象使用。

  爲了建立Socket,程序可以調用Socket函數,該函數返回一個類似於文件描述符的句柄。通過socket調用返回一個socket描述符後,在使用socket進行網絡傳輸以前,必須配置該socket。面向連接的客戶程序使用Connect函數來配置socket並與遠端服務器建立一個TCP連接,其函數原型爲:int connect(int sockfd, struct sockaddr *serv_addr,int addrlen); Send()和recv()這兩個函數用於面向連接的socket上進行數據傳輸。在用j2EE進行web開發時socket只是被封裝了而已,變成了底層的東西。在web開發這一端被隱藏了。

發佈了54 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章