Socket通信原理簡介

何謂socket

計算機,顧名思義即是用來做計算。因而也需要輸入和輸出,輸入需要計算的條件,輸出計算結(jié)果。這些輸入輸出可以抽象為I/O(input output)。

Unix的計算機處理IO是通過文件的抽象。計算機不同的進程之間也有輸入輸出,也就是通信。因此這這個通信也是通過文件的抽象文件描述符來進行。

在同一臺計算機,進程之間可以這樣通信,如果是不同的計算機呢?網(wǎng)絡(luò)上不同的計算機,也可以通信,那么就得使用網(wǎng)絡(luò)套接字(socket)。socket就是在不同計算機之間進行通信的一個抽象。他工作于TCP/IP協(xié)議中應(yīng)用層和傳輸層之間的一個抽象。如下圖:

socket.jpg

服務(wù)器通信

socket保證了不同計算機之間的通信,也就是網(wǎng)絡(luò)通信。對于網(wǎng)站,通信模型是客戶端服務(wù)器之間的通信。兩個端都建立一個socket對象,然后通過socket對象對數(shù)據(jù)進行傳輸。通常服務(wù)器處于一個無線循環(huán),等待客戶端連接:

socket3.jpg

socket 通信實例

socket接口是操作系統(tǒng)提供的,調(diào)用操作系統(tǒng)的接口。當(dāng)然高級語言一般也封裝了好用的函數(shù)接口,下面用python代碼寫一個簡單的socket服務(wù)端例子:

server.py

import socket

HOST = 'localhost'      # 服務(wù)器主機地址
PORT = 5000             # 服務(wù)器監(jiān)聽端口
BUFFER_SIZE = 2048      # 讀取數(shù)據(jù)大小

# 創(chuàng)建一個套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
# 綁定主機和端口
sock.bind((HOST, PORT))
# 開啟socket監(jiān)聽
sock.listen(5)


print 'Server start, listening {}'.format(PORT)


while True:
    # 建立連接,連接為建立的時候阻塞
    conn, addr = sock.accept()
    while True:
        # 讀取數(shù)據(jù),數(shù)據(jù)還沒到來阻塞
        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

# 創(chuàng)建客戶端套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接到服務(wù)器
sock.connect((HOST, PORT))

try:
    message = "Hello"
    # 發(fā)起數(shù)據(jù)給服務(wù)器
    sock.sendall(message)
    amount_received = 0
    amount_expected = len(message)
    while amount_received < amount_expected:
        # 接收服務(wù)器返回的數(shù)據(jù)
        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三次握手又是如何體現(xiàn)的呢?什么是三次握手呢?

  • 第一握:首先客戶端發(fā)送一個syn,請求連接,
  • 第二握:服務(wù)器收到之后確認(rèn),并發(fā)送一個 syn ack應(yīng)答
  • 第三握:客戶端接收到服務(wù)器發(fā)來的應(yīng)答之后再給服務(wù)器發(fā)送建立連接的確定。

用下面的比喻就是

C:約么?

S:約

C:好的

約會

這樣就建立了一個TCP連接會話。如果是要斷開連接,大致過程是:

tcp.png

上圖也很清晰的表明了三次握手的socket具體過程。

  1. 客戶端socket對象connect調(diào)用之后進行阻塞,此過程發(fā)送了一個syn。
  2. 服務(wù)器內(nèi)核完成三次握手,即發(fā)送syn和ack應(yīng)答。
  3. 客戶端socket對象收到服務(wù)端發(fā)送的應(yīng)答之后,再發(fā)送一個ack給服務(wù)器,并返回connect調(diào)用,建立連接。
  4. 服務(wù)器socket對象接受客戶端最后一次握手確定ack建立連接。
  5. 此時服務(wù)端調(diào)用accept,則從連接隊列中將之前建立的連接取出返回。

至此,客戶端和服務(wù)器的socket通信連接建立完成,剩下的就是兩個端的連接對象收發(fā)數(shù)據(jù),從而完成網(wǎng)絡(luò)通信。

文中圖片來源網(wǎng)絡(luò)

更多細(xì)節(jié),可以閱讀 TCP握手與socket通信細(xì)節(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容