好多天前就想寫的,可是拖延症暫時沒藥醫。。。
socket程式設計過程中,有幾個前提(在unp的前言以及第一章中有提到)。1.需要一定的程式語言基礎,例如c語言;2.需要有一定的tcp/ip網路協議棧知識,至少知道tcp和udp的連線和釋放(話說udp不需要連線);3.如果可能,最好對作業系統(例如linux)有一定了解。然後,就可以開搞了。
一般而言,socket程式設計分為客戶端和服務端程式設計,socket提供在這兩者之間進行資訊互動。基本的流程如下:
其中,read和write屬於linux/unix下的系統呼叫,通常還可以用recv和send函式代替。這張圖引用自unp第四章,使用系統呼叫的原因主要是為了表明,socket函式返回的socket描述符可以和linux系統的本地檔案描述符同樣對待,因此也能夠使用close函式來關閉乙個套接字。
tcp屬於全雙工通訊,因此乙個套接字描述符擁有兩個緩衝區,乙個傳送,乙個接收,即tcp socket可以同時進行資料的收發而相互不影響。
對於客戶端而言,socket函式產生套接字描述符,connect函式連線到服務端,服務端資訊(例如ip位址,埠號等)放在乙個socket_in結構中。通常而言,客戶端不需要使用bind函式,但如果非要使用,也可以把客戶端繫結到乙個特定的ip或埠號(這兩個可以任意組合)。其中,埠號小於1024(系統服務使用)需要root許可權分配,ip位址則必須是本地網路介面的ip位址,即bind函式可以將客戶端繫結到本機的乙個特定的網路介面上,這樣往外發資料就都使用這個特定的介面,否則根據目的位址的不同會通過不同的介面傳送。例如,如果不繫結ip位址,傳送資料到本地環迴位址(127.0.0.1)將同樣使用本地介面,而到本機的區域網位址則使用有線網路介面(例如eth0),具體連線可以通過netstat檢視。因此,如果要限制系統中只能開乙個客戶端,可以將客戶端的ip和埠全部綁死,這樣開第二個客戶端的時候connect函式就會返回「address already in use」錯誤。
關於檔案描述符(套接字描述符),在看unp談及最簡單的併發時(使用fork),迴圈裡是這樣寫的:
for(;;)這裡涉及到fork函式的呼叫。 fork函式建立了乙個新的程序,然後把舊程序的一切都複製了一遍(實際上只有兩者產生不同時才複製),所以實際上就存在了兩個監聽套接字和連線套接字描述符,在linux中就是對套接字描述符的鏈結計數器+1,所以在子程序中關閉監聽套接字只是計數器-1的操作,不會真的關閉連線。close(connfd);
}
初學socket程式設計時,容易遇到許多的坑,例如,tcp的狀態轉換,見下圖:
tcp連線的狀態並不是《計算機網路》(謝希仁版,教材)那本書中提到那麼簡單,而且連線終止也更加細化了一些。如果不能理解(記住)這些狀態,時不時就要被坑一下。
又例如,socket使用網路進行資料傳輸,所以各種網路中的突發狀況都會在通訊過程中發生,而服務端和客戶端也可能發生許多不可預知的錯誤。例如,伺服器或客戶端異常關閉,資料的位元組序不同,客戶端和服務端字大小不同(例如乙個是32位另乙個是64位),網路突然斷開等等。
所以,簡單的處理就是對各個函式呼叫過程中產生的錯誤資訊(產生訊號)進行相應的處理,例如新增訊號處理函式等。
socket程式設計筆記
listen函式僅會被tcp伺服器端呼叫,主要完成兩件事情1 當socket函式建立乙個套接字時,它被假設為主動套接字,既是將呼叫connect函式發起連線的客戶套接字,而listen函式把乙個未連線的套接字轉換成乙個被動套接字,指示核心應該接受指向該套接字的連線請求。2 listen函式的第二個引...
Java程式設計思想 筆記001
我們之所以將自然界分解,組織成各種概念,並按其 含義分類 主要是因為我們是整個口語交流社會共同遵守的協定和參與者,這個協定以語言的形式的形式固定下來.除非咱曾這個規定中規定的有關語言資訊的 組織和分類 否則我們根本無法交談 benjamin lee whorf 1897 1941 計算機革命起源於機...
socket程式設計(學習筆記)
tcp ip協議找到目標位址,埠號標識軟體。public static void main string args throws exception 客戶端 public static void main string args 多執行緒通訊 構造執行緒,執行邏輯 thread thread 1 n...