新聞中心
在計(jì)算機(jī)網(wǎng)絡(luò)中,Socket是一種常用的通信方式,它提供了在不同主機(jī)之間進(jìn)行數(shù)據(jù)傳輸?shù)慕涌?,在Socket編程中,有兩種主要的連接方式:短連接和長連接,心跳包也是網(wǎng)絡(luò)通信中常用的一種機(jī)制,用于檢測連接的有效性,本文將對(duì)這三種技術(shù)進(jìn)行詳細(xì)的分析。

創(chuàng)新互聯(lián)建站專注于集寧企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,電子商務(wù)商城網(wǎng)站建設(shè)。集寧網(wǎng)站建設(shè)公司,為集寧等地區(qū)提供建站服務(wù)。全流程按需制作網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務(wù)
1. 短連接
短連接是指在建立連接后,數(shù)據(jù)發(fā)送完畢即斷開連接,這種方式適用于數(shù)據(jù)量較小、傳輸頻率較高的場景,短連接的優(yōu)點(diǎn)是實(shí)現(xiàn)簡單,資源消耗較少;缺點(diǎn)是頻繁建立和斷開連接,增加了網(wǎng)絡(luò)開銷。
在Python中,可以使用`socket`庫來實(shí)現(xiàn)短連接,以下是一個(gè)簡單的短連接示例:
import socket
# 創(chuàng)建socket對(duì)象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接到服務(wù)器
server_address = ('localhost', 8080)
s.connect(server_address)
# 發(fā)送數(shù)據(jù)
data = 'Hello, World!'
s.sendall(data.encode())
# 關(guān)閉連接
s.close()
2. 長連接
長連接是指在建立連接后,保持連接狀態(tài),直到客戶端或服務(wù)器主動(dòng)關(guān)閉連接,這種方式適用于數(shù)據(jù)量較大、傳輸頻率較低的場景,長連接的優(yōu)點(diǎn)是減少了頻繁建立和斷開連接的開銷,提高了傳輸效率;缺點(diǎn)是占用的資源較多。
在Python中,可以使用`socket`庫來實(shí)現(xiàn)長連接,以下是一個(gè)簡單的長連接示例:
import socket
# 創(chuàng)建socket對(duì)象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 連接到服務(wù)器并保持連接狀態(tài)
server_address = ('localhost', 8080)
s.connect(server_address)
s.settimeout(60) # 設(shè)置超時(shí)時(shí)間,避免死鎖
# 發(fā)送數(shù)據(jù)
data = 'Hello, World!'
while True:
try:
s.sendall(data.encode())
break # 發(fā)送成功,跳出循環(huán)
except socket.error as e:
if e.errno == socket.errno.EPIPE: # 對(duì)方已關(guān)閉連接,重新建立連接
print('Connection closed by server, reconnecting...')
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(server_address)
else:
raise e
3. 心跳包
心跳包是一種用于檢測連接有效性的數(shù)據(jù)包,在長連接中,客戶端和服務(wù)器需要定期發(fā)送心跳包來確認(rèn)對(duì)方仍然在線,如果一段時(shí)間內(nèi)沒有收到對(duì)方的心跳包,可以認(rèn)為連接已經(jīng)失效,此時(shí)可以主動(dòng)關(guān)閉連接或者重新建立連接,心跳包通常包含一個(gè)序列號(hào)和一個(gè)時(shí)間戳,用于判斷數(shù)據(jù)包的新舊程度。
在Python中,可以使用`socket`庫來實(shí)現(xiàn)心跳包的發(fā)送和接收,以下是一個(gè)簡單的心跳包示例:
import socket
import time
import struct
from hashlib import sha1
# 創(chuàng)建socket對(duì)象并連接到服務(wù)器
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 8080)
s.connect(server_address)
s.settimeout(60) # 設(shè)置超時(shí)時(shí)間,避免死鎖
# 初始化序列號(hào)和時(shí)間戳
seq = 0
timestamp = int(time.time()) & 0xFFFFFFFFFFFFFFFFL # 使用長整數(shù)表示時(shí)間戳,避免溢出問題
hash_str = f'{seq}{timestamp}'.encode() # 將序列號(hào)和時(shí)間戳拼接成字符串,并進(jìn)行哈希處理,生成唯一的標(biāo)識(shí)符
hash_value = sha1(hash_str).digest()[:4] # 取哈希值的前4個(gè)字節(jié)作為校驗(yàn)碼,與原始數(shù)據(jù)一起發(fā)送和接收,用于檢測數(shù)據(jù)包的完整性和一致性
data = struct.pack('>I', timestamp) + hash_value + struct.pack('>I', seq) + b'heartbeat' # 將數(shù)據(jù)按照一定的格式打包成二進(jìn)制數(shù)據(jù)流,方便傳輸和解析
# 發(fā)送心跳包并接收響應(yīng)
while True:
s.sendall(data) # 發(fā)送心跳包
try:
response = s.recv(1024) # 接收響應(yīng)數(shù)據(jù),最大接收1024字節(jié)的數(shù)據(jù)包,防止緩沖區(qū)溢出問題
if len(response) < len(data): # 如果接收到的數(shù)據(jù)長度小于發(fā)送的數(shù)據(jù)長度,說明對(duì)方已經(jīng)關(guān)閉了連接,跳出循環(huán),關(guān)閉本地連接并退出程序
print('Connection closed by server, exiting...')
s.close()
break
received_timestamp, received_hash_value, received_seq, response_data = struct.unpack('>IIII', response[:20]) # 解析接收到的數(shù)據(jù),獲取序列號(hào)、時(shí)間戳、校驗(yàn)碼和響應(yīng)數(shù)據(jù)等字段的值,并進(jìn)行比較和驗(yàn)證,判斷數(shù)據(jù)包的新舊程度和一致性是否正確
if received_timestamp != timestamp or received_hash_value != hash_value or received_seq != (seq + 1): # 如果序列號(hào)、時(shí)間戳或校驗(yàn)碼等字段的值與本地的值不一致,說明數(shù)據(jù)包已經(jīng)被篡改或者丟失,拋出異常并重新發(fā)送心跳包;否則,更新本地的序列號(hào)、時(shí)間戳和校驗(yàn)碼等字段的值,并處理響應(yīng)數(shù)據(jù)(例如打印出來)
raise ValueError('Invalid heartbeat packet')
print(f'Received response: {response_data}') # 處理響應(yīng)數(shù)據(jù)(例如打印出來)
except socket.error as e: # 如果發(fā)生網(wǎng)絡(luò)錯(cuò)誤(例如對(duì)方已經(jīng)關(guān)閉了連接),跳出循環(huán),關(guān)閉本地連接并退出程序;否則,繼續(xù)發(fā)送心跳包并接收響應(yīng)數(shù)據(jù)(例如打印出來)
print('Network error:', e)
s.close()
break
新聞標(biāo)題:socket中的短連接與長連接以及心跳包示例分析「tcp長連接心跳包」
網(wǎng)頁鏈接:http://m.fisionsoft.com.cn/article/cosjhjh.html


咨詢
建站咨詢
