06.26自我總結
1.關於Socket
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。python
socket模板已經爲咱們封裝好了,咱們只須要遵循socket的規定去編程,寫出的程序天然就是遵循tcp/udp標準的。編程
- 注意:也有人將socket說成ip+port,ip是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺機器上的一個應用程序,ip地址是配置到網卡上的,而port是應用程序開啓的,ip與port的綁定就標識了互聯網中獨一無二的一個應用程序,而程序的pid是同一臺機器上不一樣進程或者線程的標識。
2.套接字工做流程
3.套接字的函數
s都爲經過socket模塊生成
設計模式
import socket
# socket_family 能夠是 AF_UNIX 或 AF_INET。socket_type 能夠是 SOCK_STREAM 或 SOCK_DGRAM。protocol 通常不填,默認值爲 0
socket.socket(socket_family, socket_type, protocal=0)
# 獲取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 獲取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 因爲 socket 模塊中有太多的屬性。咱們在這裏破例使用了'from module import *'語句。使用 'from socket import *',咱們就把 socket 模塊裏的全部屬性都帶到咱們的命名空間裏了,這樣能大幅減短咱們的代碼
s = socket(AF_INET, SOCK_STREAM)
1.服務器套接字函數
s.bind() |
綁定(主機,端口號)到套接字 注:(127.0.0.1)表示本地ip |
s.listen() |
開始TCP監聽 |
s.accept() |
被動接受TCP客戶的鏈接,(阻塞式)等待鏈接的到來 |
2.客戶端套接字函數
s.connect() |
主動初始化TCP服務器鏈接 |
s.connect_ex() |
connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常 |
3.公共用途的函數
s.recv() |
接收TCP數據 |
s.send() |
發送TCP數據(send在待發送數據量大於己端緩存區剩餘空間時,數據丟失,不會發完) |
s.sendall() |
發送完整的TCP數據(本質就是循環調用send,sendall在待發送數據量大於己端緩存區剩餘空間時,數據不丟失,循環調用send直到發完) |
s.recvfrom() |
接收UDP數據 |
s.sendto() |
發送UDP數據 |
s.getpeername() |
鏈接到當前套接字的遠端的地址 |
s.getsockname() |
當前套接字的地址 |
s.getsockopt() |
返回指定套接字的參數 |
s.setsockopt() |
設置指定套接字的參數 |
s.close() |
關閉套接字 |
4.面向鎖套接字
s.setblocking() |
設置套接字的阻塞與非阻塞模式 |
s.settimeout() |
設置阻塞套接字操做的超時時間 |
s.gettimeout() |
獲得阻塞套接字操做的超時時間 |
5.面向文件套接字
s.fileno() |
套接字的文件描述符 |
s.makefile() |
建立一個與該套接字相關的文件 |
4.示例
1.服務端
import socket
#一、買手機
phone = socket.socket(socket.AF_INET,
socket.SOCK_STREAM) #tcp稱爲流式協議,udp稱爲數據報協議SOCK_DGRAM
# print(phone)
#二、插入/綁定手機卡
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1', 8080))
#三、開機
phone.listen(5) # 半鏈接池,限制的是請求數
#四、等待電話鏈接
print('start....')
while True: # 鏈接循環
conn, client_addr = phone.accept() #(三次握手創建的雙向鏈接,(客戶端的ip,端口))
# print(conn)
print('已經有一個鏈接創建成功', client_addr)
#五、通訊:收\發消息
while True: # 通訊循環
try:
print('服務端正在收數據...')
data = conn.recv(1024) #最大接收的字節數,沒有數據會在原地一直等待收,即發送者發送的數據量必須>0bytes
# print('===>')
if len(data) == 0: break #在客戶端單方面斷開鏈接,服務端纔會出現收空數據的狀況
print('來自客戶端的數據', data)
conn.send(data.upper())
except ConnectionResetError:
break
#六、掛掉電話鏈接
conn.close()
#七、關機
phone.close()
2.客戶端
import socket
#一、買手機
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# print(phone)
#二、撥電話
phone.connect(('127.0.0.1', 8080)) # 指定服務端ip和端口
#三、通訊:發\收消息
while True: # 通訊循環
msg = input('>>: ').strip() #msg=''
if len(msg) == 0: continue
phone.send(msg.encode('utf-8'))
# print('has send----->')
data = phone.recv(1024)
# print('has recv----->')
print(data)
#四、關閉
phone.close()