1. 程式人生 > >網路程式設計之Socket

網路程式設計之Socket

網路程式設計之Socket

我們已經知道,假設我現在要寫一個程式,給另一臺計算機發資料,必須通過tcp/ip協議 ,但具體的實現過程是什麼呢?我應該怎麼操作才能把資料封裝成tcp/ip的包,又執行什麼指令才能把資料發到對端機器上呢? 不能只有世界觀,沒有方法論呀。。。此時,socket隆重登場,簡而言之,socket這個東東干的事情,就是幫你把tcp/ip協議層的各種資料封裝啦、資料傳送、接收等通過程式碼已經給你封裝好了,你只需要呼叫幾行程式碼,就可以給別的機器發訊息了。

一、Socket介紹

1、什麼是Socket

Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層。它是一組介面。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部。

socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆檔案”,都可以用“開啟open –> 讀寫write/read –> 關閉close”模式 來操作。Socket就是該模式的一個實現,socket即是一種特殊的檔案,一些socket函式就是對其進行的操作(讀/寫IO、開啟、關閉)。

你想給另一臺計算機發訊息,你知道他的IP地址,他的機器上同時執行著qq、迅雷、word、瀏覽器等程式,你想給他的qq發訊息,那想一下,你現在只能通過ip找到他的機器,但如果讓這臺機器知道把訊息發給qq程式呢?答案就是通過port,一個機器上可以有0-65535個埠,你的程式想從網路上收發資料,就必須繫結一個埠,這樣,遠端發到這個埠上的資料,就全會轉給這個程式。

2、Socket通訊套路

當通過socket建立起2臺機器的連線後,本質上socket只幹2件事,一是收資料,一是發資料,沒資料時就等著。

socket 建立連線的過程跟我們現實中打電話比較像,打電話必須是打電話方和接電話方共同完成的事情,我們分別看看他們是怎麼建立起通話的。

接電話方:

1.首先你得有個電話

2.你的電話要有號碼

3.你的電話必須連上電話線

4.開始在家等電話

5.電話鈴響了,接起電話,聽到對方的聲音

打電話方:

1.首先你得有個電話

2.輸入你想撥打的電話

3.等待對方接聽

4.say “hi 約麼,我有七天酒店的打折卡噢~”

5.等待迴應——》響應迴應——》等待迴應。。。。

把上述事件翻譯成socket通訊

接電話方(socket伺服器端):

1.首先你得有個電話\(生成socket物件\)

2.你的電話要有號碼\(繫結本機ip+port\)

3.你的電話必須連上電話線\(連網\)

4.開始在家等電話\(開始監聽電話listen\)

5.電話鈴響了,接起電話,聽到對方的聲音\(接受新連線\)

打電話方(socket客戶端):

1.首先你得有個電話\(生成socket物件\)

2.輸入你想撥打的電話\(connect 遠端主機ip+port\)

3.等待對方接聽

4.say “hi 約麼,我有七天酒店的打折卡噢~”\(send\(\) 發訊息。。。\)

5.等待迴應——》響應迴應——》等待迴應。。。。

二、Socket套接字方法

1、socket例項類

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

family(socket家族)

  • socket.AF_UNIX:用於本機程序間通訊,為了保證程式安全,兩個獨立的程式(程序)間是不能互相訪問彼此的記憶體的,但為了實現程序間的通訊,可以通過建立一個本地的socket來完成。
  • socket.AF_INET:(還有AF_INET6被用於ipv6,還有一些其他的地址家族,不過,他們要麼是隻用於某個平臺,要麼就是已經被廢棄,或者是很少被使用,或者是根本沒有實現,所有地址家族中,AF_INET是使用最廣泛的一個,python支援很多種地址家族,但是由於我們只關心網路程式設計,所以大部分時候我麼只使用AF_INET)。

socket type 型別

  • socket.SOCK_STREAM # for TCP
  • scoket.SOCK_DGRAM # for UDP
  • socket.SOCK_RAW # 原始套接字,普通的套接字無法處理ICMP、IGMP等網路報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由使用者構造IP頭。
  • socket.SOCK_RDM # 是一種可靠的UDP形式,即保證交付資料但不保證順序。SOCK_RAM用來提供對原始協議的低階訪問,在需要執行某些特殊操作時使用,如傳送ICMP報文。SOCK_RAM通常僅限於高階使用者或管理員執行的程式使用。
  • socket.SOCK_SEQPACKET # 廢棄了。

Only SOCK_STREAM and SOCK_DGRAM appear to be generally useful.

proto=0

可忽略,特殊用途才考慮。

fileno=None

可忽略,特殊用途才考慮。

2、服務端套接字函式

設s為socket例項化的一個物件

  • s.bind() 繫結(主機,埠號)到套接字。
  • s.listen() 開始TCP監聽。
  • s.accept() 被動接收TCP客戶的連線,(阻塞式)等待連線的到來。

3、客戶端套接字函式

設s為socket例項化的一個物件

  • s.connect() 主動初始化TCP伺服器連線。
  • s.connect_ex() 是connect()函式的擴充套件版本,出錯時返回出錯碼,而不是丟擲異常。

4、公共用途的套接字函式

設s為socket例項化的一個物件

  • s.recv() 接收資料。
  • s.send() 傳送資料(send在待發送資料量大於己端快取區剩餘空間時,資料丟失,不會發完)
  • s.sendall() 傳送完整的TCP資料(本質就是迴圈呼叫send,sendall在待發送資料量大於己端快取區剩餘空間時,資料不丟失,迴圈呼叫send直到發完)。
  • s.recvform() Receive data from the socket. The return value is a pair (bytes, address)
  • s.getpeername() 連線到當前套接字的遠端的地址。
  • s.close() 關閉套接字。
  • socket.setblocking(flag) # True or False,設定socket為非阻塞模式。
  • socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0) 返回遠端主機的地址資訊,例如:socket.getaddrinfo('luffycity.com', 80)
  • socket.getqdn() 拿到本機的主機名。
  • socket.gethostbyname() 通過域名解析ip地址。