Socket相關知識
所謂socket通常也稱作"套接字",應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。 以Java爲例,Socket和ServerSocket類庫位於java .net包中。ServerSocket用於服務器端,Socket是建立網絡連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例, 操作這個實例,完成所需的會話。對於一個網絡連接來說,套接字是平等的,並沒有差別,不因爲在服務器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。
常用的Socket類型有兩種:流式Socket(SOCK_STREAM)和數據報式Socket(SOCK_DGRAM)。流式是一種面向連接的Socket,針對於面向連接的TCP服務應用;數據報式Socket是一種無連接的Socket,對應於無連接的UDP服務應用。
1、socket通信方式
socket通信方式主要有以下三大類:
(一)SERVER/CLIENT方式
1.一個Client方連接一個Server方,或稱點對點(peer to peer):
2.多個Client方連接一個Server方,這也是通常的併發服務器方式。
3.一個Client方連接多個Server方,這種方式很少見,主要用於一個客戶向多個服務器發送請求情況。
2.多個Client方連接一個Server方,這也是通常的併發服務器方式。
3.一個Client方連接多個Server方,這種方式很少見,主要用於一個客戶向多個服務器發送請求情況。
(二)連接方式
1.長連接
Client方與Server方先建立通訊連接,連接建立後不斷開,然後再進行報文發送和接收。這種方式下由於通訊連接一直存在,可以用下面命令查看連接是否建立:
netstat –f inet|grep 端口號(如5678)。
此種方式常用於點對點通訊。
netstat –f inet|grep 端口號(如5678)。
此種方式常用於點對點通訊。
2.短連接
Client方與Server每進行一次報文收發交易時才進行通訊連接,交易完畢後立即斷開連接。此種方式常用於一點對多點通訊,比如多個Client連接一個Server.
(三)發送接收方式
1.異步
報文發送和接收是分開的,相互獨立的,互不影響。這種方式又分兩種情況:
(1)異步雙工:接收和發送在同一個程序中,有兩個不同的子進程分別負責發送和接收
(2)異步單工:接收和發送是用兩個不同的程序來完成。
(2)異步單工:接收和發送是用兩個不同的程序來完成。
2.同步
報文發送和接收是同步進行,既報文發送後等待接收返回報文。同步方式一般需要考慮超時問題,即報文發上去後不能無限等待,需要設定超時時間,超過該時間發送方不再等待讀返回報文,直接通知超時返回。
實際通信方式是這三類通信方式的組合。比如一般書上提供的TCP/IP範例程序大都是同步短連接的SERVER/CLIENT程序。有的組合是基本不用的,比較常用的有價值的組合是以下幾種:
同步短連接Server/Client
同步長連接Server/Client
異步短連接Server/Client
異步長連接雙工Server/Client
異步長連接單工Server/Client
同步長連接Server/Client
異步短連接Server/Client
異步長連接雙工Server/Client
異步長連接單工Server/Client
其中異步長連接雙工是最爲複雜的一種通信方式,有時候經常會出現在不同銀行或不同城市之間的兩套系統之間的通信。
2.socket報文處理方式
socket通信報文格式多樣,因此也必須設計對應的讀寫報文的接收和發送報文函數。
(一)阻塞與非阻塞方式
1.非阻塞方式
讀函數不停地進行讀動作,如果沒有報文接收到,等待一段時間後超時返回,這種情況一般需要指定超時時間。
2.阻塞方式
如果沒有報文接收到,則讀函數一直處於等待狀態,直到有報文到達。
(二)循環讀寫方式
1.一次直接讀寫報文
在一次接收或發送報文動作中一次性不加分別地全部讀取或全部發送報文字節。
2.不指定長度循環讀寫
這一般發生在短連接進程中,受網絡路由等限制,一次較長的報文可能在網絡傳輸過程中被分解成了好幾個包。一次讀取可能不能全部讀完一次報文,這就需要循環讀報文,直到讀完爲止。
3.帶長度報文頭循環讀寫
這種情況一般是在長連接進程中,由於在長連接中沒有條件能夠判斷循環讀寫什麼時候結束,所以必須要加長度報文頭。讀函數先是讀取報文頭的長度,再根據這個長度去讀報文.實際情況中,報頭的碼制格式還經常不一樣,如果是非ASCII碼的報文頭,還必須轉換成ASCII,常見的報文頭碼制有:
(1)n個字節的ASCII碼
(2)n個字節的BCD碼
(3)n個字節的網絡整型碼
(1)n個字節的ASCII碼
(2)n個字節的BCD碼
(3)n個字節的網絡整型碼
以上是幾種比較典型的讀寫報文方式,可以與通信方式模板一起預先提供一些典型的API讀寫函數。當然在實際問題中,可能還必須編寫與對方報文格式配套的讀寫API。在實際情況中,往往需要把我們自己的系統與別人的系統進行連接,有了以上模板與API,可以說連接任何方式的通信程序都不存在問題。
3、SOCKET連接過程
根據連接啓動的方式以及本地套接字要連接的目標,套接字之間的連接過程可以分爲三個步驟:服務器監聽,客戶端請求,連接確認。
服務器監聽:是服務器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網絡狀態。
客戶端請求:是指由客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然後就向服務器端套接字提出連接請求。
連接確認:是指當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求,它就響應客戶端套 接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,連接就建立好了。而服務器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。
系統特殊要求說明
系統採用的是同步短連接Server/Client方式,無論Server還是client在報文處理方式上,都採用一次直接讀寫報文+阻塞方式。通信由Client主動發起,一次性發送報文給Server後,主動關閉Socket輸出,服務器收到Client的關閉輸出響應後,停止socket輸入,並開始處理業務,生成響應報文返回客戶端。
服務器處理流程如下:
對於連入的客戶端,服務器要求其設置連接超時時間、並在輸入數據完成後,主動停止輸出流;如果客戶端沒有主動停止輸出流,則直到連接超時或者關閉輸入流、輸出流和socket時服務器纔會返回數據。在Java中,主動停止輸出流的函數爲socket.shutdownOutput()。
各類語言客戶端關閉輸入輸出流函數說明
1、C語言
int shutdown(int socket,int how)
函數說明 shutdown()用來終止參數s所指定的socket讀取或者傳輸操作,參數how有下列幾種情況:
how=0 終止讀取操作。
how=1 終止傳送操作
how=2 終止讀取及傳送操作
how=1 終止傳送操作
how=2 終止讀取及傳送操作
2、php語言
boolean socket_shutdown(resource socket, integer how)
socket_shutdown函數關閉一個socket的輸入輸出。設置how爲0則中止接受數據,設置爲1則停止發送數據,設置爲2則中止二者操作。
3、LoadRunner的Socket協議語言
int lrs_disable_socket ( char *s_desc, int operation );
lrs_disable_socket函數關閉一個socket的輸入輸出。設置operation爲SEND則中止接受數據,設置爲RECEIVE則停止發送數據,設置爲SEND-RECEIVE則中止二者操作。
4、Java語言
socket.shutdownInput():關閉Socket的輸入流;
socket.shutdownOuput():關閉Socket的輸出流。