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的區別就是不用建立連接,客戶端只是收發消息,並不會與服務器建立連接