亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

什么是Socket?

Socket的中文翻譯過來就是“套接字”。套接字是什么,我們先來看看它的英文含義:插座。

Socket就像一個電話插座,負責連通兩端的電話,進行點對點通信,讓電話可以進行通信,端口就像插座上的孔,端口不能同時被其他進程占用。而我們建立連接就像把插頭插在這個插座上,創建一個Socket實例開始監聽后,這個電話插座就時刻監聽著消息的傳入,誰撥通我這個“IP地址和端口”,我就接通誰。

實際上,Socket是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層復雜的操作抽象為幾個簡單的接口,供應用層調用實現進程在網絡中的通信。Socket起源于UNIX,在Unix一切皆文件的思想下,進程間通信就被冠名為文件描述符(file desciptor),Socket是一種“打開—讀/寫—關閉”模式的實現,服務器和客戶端各自維護一個“文件”,在建立連接打開后,可以向文件寫入內容供對方讀取或者讀取對方內容,通訊結束時關閉文件。

另外我們經常說到的Socket所在位置如下圖:

Socket通信過程

Socket保證了不同計算機之間的通信,也就是網絡通信。對于網站,通信模型是服務器與客戶端之間的通信。兩端都建立了一個Socket對象,然后通過Socket對象對數據進行傳輸。通常服務器處于一個無限循環,等待客戶端的連接。

一圖勝千言,下面是面向連接的TCP時序圖:

客戶端過程:

客戶端的過程比較簡單,創建Socket,連接服務器,將Socket與遠程主機連接(注意:只有TCP才有“連接”的概念,一些Socket比如UDP、ICMP和ARP沒有“連接”的概念),發送數據,讀取響應數據,直到數據交換完畢,關閉連接,結束TCP對話。

import socket

import sys

if __name__ == '__main__':

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 創建Socket連接

sock.connect(('127.0.0.1', 8001)) # 連接服務器

while True:

data = input('Please input data:')

if not data:

break

try:

sock.sendall(data)

except socket.error as e:

print('Send Failed...', e)

sys.exit(0)

print('Send Successfully')

res = sock.recv(4096) # 獲取服務器返回的數據,還可以用recvfrom()、recv_into()等

print(res)

sock.close()sock.sendall(data)

這里也可用send()方法:不同在于sendall()在返回前會嘗試發送所有數據,并且成功時返回None,而send()則返回發送的字節數量,失敗時都拋出異常。

服務端過程:

咱再來聊聊服務端的過程,服務端先初始化Socket,建立流式套接字,與本機地址及端口進行綁定,然后通知TCP,準備好接收連接,調用accept()阻塞,等待來自客戶端的連接。如果這時客戶端與服務器建立了連接,客戶端發送數據請求,服務器接收請求并處理請求,然后把響應數據發送給客戶端,客戶端讀取數據,直到數據交換完畢。最后關閉連接,交互結束。

import socket

import sys

if __name__ == '__main__':

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 創建Socket連接(TCP)

print('Socket Created')

try:

sock.bind(('127.0.0.1', 8001)) # 配置Socket,綁定IP地址和端口號

except socket.error as e:

print('Bind Failed...', e)

sys.exit(0)

sock.listen(5) # 設置最大允許連接數,各連接和Server的通信遵循FIFO原則

while True: # 循環輪詢Socket狀態,等待訪問

conn, addr = sock.accept()

try:

conn.settimeout(10) # 獲得一個連接,然后開始循環處理這個連接發送的信息

# 如果要同時處理多個連接,則下面的語句塊應該用多線程來處理

while True:

data = conn.recv(1024)

print('Get value ' + data, end='nn')

if not data:

print('Exit Server', end='nn')

break

conn.sendall('OK') # 返回數據

except socket.timeout: # 建立連接后,該連接在設定的時間內沒有數據發來,就會引發超時

print('Time out')

conn.close() # 當一個連接監聽循環退出后,連接可以關掉

sock.close()conn, addr = sock.accept()

調用accept()時,Socket會進入“waiting”狀態。客戶請求連接時,方法建立連接并返回服務器。accept()返回一個含有兩個元素的元組(conn, addr)。第一個元素conn是新的Socket對象,服務器必須通過它與客戶通信;第二個元素addr是客戶的IP地址及端口。

data = conn.recv(1024)

接下來是處理階段,服務器和客戶端通過send()和recv()通信(傳輸數據)。

服務器調用send(),并采用字符串形式向客戶發送信息,send()返回已發送的字符個數。

服務器調用recv()從客戶接收信息。調用recv()時,服務器必須指定一個整數,它對應于可通過本次方法調用來接收的最大數據量。recv()在接收數據時會進入“blocked”狀態,最后返回一個字符串,用它表示收到的數據。如果發送的數據量超過了recv()所允許的,數據會被截短。多余的數據將緩沖于接收端,以后調用recv()時,多余的數據會從緩沖區刪除(以及自上次調用recv()以來,客戶可能發送的其它任何數據)。傳輸結束,服務器調用Socket的close()關閉連接。

TCP三次握手的Socket過程:

  • 服務器調用socket()、bind()、listen()完成初始化后,調用accept()阻塞等待;
  • 客戶端Socket對象調用connect()向服務器發送了一個SYN并阻塞;
  • 服務器完成了第一次握手,即發送SYN和ACK應答;
  • 客戶端收到服務端發送的應答之后,從connect()返回,再發送一個ACK給服務器;
  • 服務器Socket對象接收客戶端第三次握手ACK確認,此時服務端從accept()返回,建立連接。

接下來就是兩個端的連接對象互相收發數據。

TCP四次揮手的Socket過程:

  • 某個應用進程調用close()主動關閉,發送一個FIN;
  • 另一端接收到FIN后被動執行關閉,并發送ACK確認;
  • 之后被動執行關閉的應用進程調用close()關閉Socket,并也發送一個FIN;
  • 接收到這個FIN的一端向另一端ACK確認。

上面的代碼是簡單的演示Socket的基本函數使用,其實不管有多復雜的網絡程序,這些基本函數都會用到。上面的服務端代碼只有處理完一個客戶端請求才會去處理下一個客戶端的請求,這樣的服務器處理能力很弱,而實際中服務器都需要有并發處理能力,為了達到并發處理,服務器就需要fork一個新的進程或者線程去處理請求。

分享到:
標簽:通信 Socket
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定