何謂socket
計算機,顧名思義即是用來做計算。因而也需要輸入和輸出,輸入需要計算的條件,輸出計算結(jié)果。這些輸入輸出可以抽象為I/O(input output)。
Unix的計算機處理IO是通過文件的抽象。計算機不同的進程之間也有輸入輸出,也就是通信。因此這這個通信也是通過文件的抽象文件描述符來進行。
在同一臺計算機,進程之間可以這樣通信,如果是不同的計算機呢?網(wǎng)絡(luò)上不同的計算機,也可以通信,那么就得使用網(wǎng)絡(luò)套接字(socket)。socket就是在不同計算機之間進行通信的一個抽象。他工作于TCP/IP協(xié)議中應(yīng)用層和傳輸層之間的一個抽象。如下圖:

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

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連接會話。如果是要斷開連接,大致過程是:

上圖也很清晰的表明了三次握手的socket具體過程。
- 客戶端socket對象connect調(diào)用之后進行阻塞,此過程發(fā)送了一個syn。
- 服務(wù)器內(nèi)核完成三次握手,即發(fā)送syn和ack應(yīng)答。
- 客戶端socket對象收到服務(wù)端發(fā)送的應(yīng)答之后,再發(fā)送一個ack給服務(wù)器,并返回connect調(diào)用,建立連接。
- 服務(wù)器socket對象接受客戶端最后一次握手確定ack建立連接。
- 此時服務(wù)端調(diào)用accept,則從連接隊列中將之前建立的連接取出返回。
至此,客戶端和服務(wù)器的socket通信連接建立完成,剩下的就是兩個端的連接對象收發(fā)數(shù)據(jù),從而完成網(wǎng)絡(luò)通信。
文中圖片來源網(wǎng)絡(luò)
更多細(xì)節(jié),可以閱讀 TCP握手與socket通信細(xì)節(jié)