socket
socket通常也稱作"套接字",用於描述IP地址和埠,應用程式通常通過"套接字"向網路發出請求或者應答網路請求,可以認為是一種計算機網路的資料結構,介面。它是網路程式設計的基礎
套接字最早起源於Unix系統,一開始使用與一臺電腦之間的程式間通訊,目前套接字分為兩種,基於檔案型和基於網路型。其中一臺主機的程式間是通過基於檔案的套接字進行通訊(AF_UNIX或者AF_LOCAL)。而還有一種基於網路的,可用於不同主機之間的通訊(AF_INET和AP_INET6),AF_INET是用於IPV4,而AF_INET6是用於IPV6。
套接字還分為面向連線的和無連線的:
- 第一種是指TCP型別套接字,在通訊前需要建立連線,這種連線是較為可靠的,使用的套接字型別是SOCK_STREAM,TCP傳輸控制協議,經常和IP協議一起使用,稱為TCP/IP協議
- 第二種主要指UDP型別的套接字,無需連線就可以進行通訊,所有速度較快,但是可靠性不高。而且資料是整個傳送,不會分成小塊。使用的套接字型別是SOCK_DGRAM,UDP協議通常也與IP協議一起使用
python中的socket模組
使用套接字的基本步驟:
- 建立套接字
socket(socket_family, socket_type, protocol)
#socket_family 就是指套接字家族可以是AF_VNIX或AF_INET
#socket_type 就是指套接字型別,即SOCK_STREAM或SOCK_DGRAM
#protocol 是協議,預設為0,一般不填
- 建立TCP/IP或者UDP/IP套接字
- 建立TCP/IP套接字
import socket tcp = socket.socket(AF_INET, SOCK_STREAM)
- 建立UDP/IP套接字
import socket ucp = socket.socket(AF_INET, SOCK_DGRAM)
- 套接字的常用函式
函式名 | 描述 |
---|---|
伺服器套接字 | |
bind((hostname, port)) | 繫結地址(注意這裡是元祖)到套接字 |
listen() | 開啟TCP監聽 |
accept() | 被動接受客戶端的連線(阻塞) |
客戶端套接字 | |
connect((hostname, port)) | 初始化TCP伺服器連線 |
connect_ex() | connect()的擴充套件版本,出錯時返回錯誤碼,而不是異常 |
公用的套接字 | |
recv() | 接收TCP的資料 |
send() | 傳送TCP資料 |
sendall() | 傳送完整的TCP資料 |
recvfrom() | 接收UDP資料 |
sendto() | 發生UDP資料,因為沒有連線,所以這裡要指定傳送的目標 |
getpeername() | 連線到當前套接字的遠端地址 |
getsockname() | 當前socket地址 |
getsockopt() | 獲得套接字的引數 |
setsockopt() | 設定套接字的引數 |
close() | 關閉套接字 |
面向模組的套接字函式 | |
setblocking() | 設定套接字是否是阻塞模式 |
settimeout() | 設定阻塞套接字操作的超時時間 |
gettimeout() | 得到阻塞套接字操作的超時時間 |
面向檔案的套接字函式 | |
fileno() | 套接字的檔案描述符 |
makefile() | 建立一個與套接字關聯的檔案物件 |
建立一個TCP伺服器和客戶端
建立TCP伺服器的基本步驟
- 建立套接字並繫結地址
- 開始監聽連線
- 接收連結併傳送資料
- 關閉套接字
程式碼如下:
import socket
HOST = '' #空字串標示127.0.0.1
PORT = 3214
sk = socket.socket() # 預設使用IPV4和TCP
sk.bind((HOST,PORT))
sk.listen(5)
cli, addr = sk.accept() # 等待連線(阻塞式),在連線到來之前會阻塞在這裡
print "Client Addr:", addr
while True:
data = cli.recv(1024)
if not data:
break
print "Recieve Data:", data.decode('utf-8')
cli.send(data)
cli.close()
建立TCP客戶端的基本步驟
- 建立套接字,連線伺服器
- 收發資料
- 關閉套接字
import socket
HOST = '127.0.0.1'
PORT = 3214
sk = socket.socket()
try:
sk.connect((HOST, PORT))
data = "hello"
while data:
sk.sendall(data)
data = sk.recv(1024)
print "Recv data:", data
data = raw_input('Please input message\n')
except socket.error as err:
print err
finally:
sk.close()
這裡的客戶端僅僅可以用來傳送訊息給服務端,而服務端會接收訊息然後重新傳送回客戶端
建立UDP伺服器和客戶端
建立UDP服務端的基本步驟
- 建立套接字並繫結地址
- 開始監聽連線
- 收發資料
- 關閉套接字
import socket
HOST = ''
PORT = 3214
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sk.bind((HOST, PORT))
data = True
while data:
data, addr = sk.recvfrom(1024)
if data == b'bye':
break
print "Recieve Data:", data.decode('utf-8')
sk.sendto(data, addr)
sk.close()
建立UDP客戶端的基本步驟
- 建立套接字
- 收發資料
- 關閉套接字
import socket
HOST = '127.0.0.1'
PORT = 3214
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
data = 'hello'
while data:
sk.sendto(data, (HOST, PORT))
if data == "bye":
break
data, addr = sk.recvfrom(1024)
print "Recv Data:", data
data = raw_input('Please message:\n')
sk.close()
# tcpclient與udpclient區別
# 建立socket時的區別
# tcp需要連結服務端
# 收發資料方法不同
這裡與TCP的區別就是不用建立連線,客戶端只是收發訊息,並不會與伺服器建立連線