Socket通訊原理簡介
阿新 • • 發佈:2019-02-06
何謂socket
計算機,顧名思義即是用來做計算。因而也需要輸入和輸出,輸入需要計算的條件,輸出計算結果。這些輸入輸出可以抽象為I/O(input output)。
Unix的計算機處理IO是通過檔案的抽象。計算機不同的程序之間也有輸入輸出,也就是通訊。因此這這個通訊也是通過檔案的抽象檔案描述符來進行。
在同一臺計算機,程序之間可以這樣通訊,如果是不同的計算機呢?網路上不同的計算機,也可以通訊,那麼就得使用網路套接字(socket)。socket就是在不同計算機之間進行通訊的一個抽象。他工作於TCP/IP協議中應用層和傳輸層之間的一個抽象。如下圖:
socket.jpg
伺服器通訊
socket保證了不同計算機之間的通訊,也就是網路通訊。對於網站,通訊模型是客戶端伺服器之間的通訊。兩個端都建立一個socket物件,然後通過socket物件對資料進行傳輸。通常伺服器處於一個無線迴圈,等待客戶端連線:
socket3.jpg
socket 通訊例項
socket介面是作業系統提供的,呼叫作業系統的介面。當然高階語言一般也封裝了好用的函式介面,下面用python程式碼寫一個簡單的socket服務端例子:
server.py
import socket
HOST = 'localhost' # 伺服器主機地址
PORT = 5000 # 伺服器監聽埠
BUFFER_SIZE = 2048 # 讀取資料大小
# 建立一個套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 繫結主機和埠
sock.bind((HOST, PORT))
# 開啟socket監聽
sock.listen(5)
print 'Server start, listening {}'.format(PORT)
while True:
# 建立連線,連線為建立的時候阻塞
conn, addr = sock.accept()
while True:
# 讀取資料,資料還沒到來阻塞
data = conn.recv(BUFFER_SIZE)
if len(data):
print 'Server Recv Data: {}' .format(data)
conn.send(data)
print 'Server Send Data: {}'.format(data)
else:
print 'Server Recv Over'
break
conn.close()
sock.close()
client.py
import socket
HOST = 'localhost'
PORT = 5000
BUFFER_SIZE = 1024
# 建立客戶端套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連線到伺服器
sock.connect((HOST, PORT))
try:
message = "Hello"
# 發起資料給伺服器
sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
# 接收伺服器返回的資料
data = sock.recv(10)
amount_received += len(data)
print 'Client Received: {}'.format(data)
except socket.errno, e:
print 'Socket error: {}'.format(e)
except Exception, e:
print 'Other exception: %s'.format(e)
finally:
print 'Closing connection to the server'
sock.close()
TCP 三次握手
python程式碼寫套接字很簡單。傳說的TCP三次握手又是如何體現的呢?什麼是三次握手呢?
- 第一握:首先客戶端傳送一個syn,請求連線,
- 第二握:伺服器收到之後確認,併發送一個 syn ack應答
- 第三握:客戶端接收到伺服器發來的應答之後再給伺服器傳送建立連線的確定。
用下面的比喻就是
C:約麼?
S:約
C:好的
約會
這樣就建立了一個TCP連線會話。如果是要斷開連線,大致過程是:
tcp.png
上圖也很清晰的表明了三次握手的socket具體過程。
- 客戶端socket物件connect呼叫之後進行阻塞,此過程傳送了一個syn。
- 伺服器核心完成三次握手,即傳送syn和ack應答。
- 客戶端socket物件收到服務端傳送的應答之後,再發送一個ack給伺服器,並返回connect呼叫,建立連線。
- 伺服器socket物件接受客戶端最後一次握手確定ack建立連線。
- 此時服務端呼叫accept,則從連線佇列中將之前建立的連線取出返回。
至此,客戶端和伺服器的socket通訊連線建立完成,剩下的就是兩個端的連線物件收發資料,從而完成網路通訊。