為何學習socket一定要先學習網際網路協議:
c/s架構的軟體是基於網路進行通訊的
網路的核心就是一堆協議,即標準,想要開發一款基於網路通訊的軟體就必須遵循這些標準
socket是處在應用層和傳輸層中間的一組介面
說到這,那麼socket到底是個什麼呢?socket是應用層與tcp/ip協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,socket其實就是乙個門面模式,它把複雜的tcp/ip協議族隱藏在socket介面後面,對使用者來說,一組簡單的介面就是全部,讓socket去組織資料,以符合指定的協議。所以,無需深究tcp/udp協議,socket已經為我們封裝好了
基於檔案型別的套接字家族:afunix基於網路型別的套接字家族:afinet
先從伺服器端說起。伺服器端先初始化socket,然後與埠繫結(bind),對埠進行監聽(listen),呼叫accept阻塞,等待客戶端連線。在這時如果有個客戶端初始化乙個socket,然後連線伺服器(connect),如果連線成功,這時客戶端與伺服器端的連線就建立了。客戶端傳送資料請求,伺服器端接收請求並處理請求,然後把回應資料傳送給客戶端,客戶端讀取資料,最後關閉連線,一次互動結束服務端套接字函式
s.bind() 繫結(主機,埠號)到套接字
s.listen() 開始tcp監聽
s.accept() 被動接受tcp客戶的連線,(阻塞式)等待連線的到來
客戶端套接字函式
s.connect() 主動初始化tcp伺服器連線
s.connect_ex() connect()函式的擴充套件版本,出錯時返回出錯碼,而不是丟擲異常
公共用途的套接字函式
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() 關閉套接字
面向鎖的套接字方法
s.setblocking() 設定套接字的阻塞與非阻塞模式
s.settimeout() 設定阻塞套接字操作的超時時間
s.gettimeout() 得到阻塞套接字操作的超時時間
面向檔案的套接字的函式
s.fileno() 套接字的檔案描述符
s.makefile() 建立乙個與該套接字相關的檔案
**示例:服務端
from socket import *
phone=socket(af_inet,sock_stream)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
conn,addr=phone.accept()
while true:
data=conn.recv(1024)
print('server===>')
print(data)
conn.send(data.upper())
conn.close()
phone.close()
客戶端
from socket import *
phone=socket(af_inet,sock_stream)
phone.connect(('127.0.0.1',8081))
while true:
msg=input('>>: ').strip()
phone.send(msg.encode('utf-8'))
print('client====>')
data=phone.recv(1024)
print(data)
注意:這時候當客戶端輸入訊息為空的話程式會卡住,那是因為無論是服務端還是客戶端都要到自己所在主機緩衝區去拿訊息,因為這時傳送為空,服務端根本就不會有任何反應,所以客戶端的緩衝區也不會有任何內容,所以這時它會一直徒勞的等待。。。這時的解決辦法當然要在客戶端想辦法,很簡單,我們不讓客戶端傳送空訊息即可,在send()方法之前加判斷:
if not msg :continue
你肯定以為這個時候就完事了,這時請嘗試斷開客戶端鏈結試試。。。試想,既然作為服務端,顧名思義就是要持續不斷的為不同的客戶端持續的提供服務,怎麼能乙個客戶端用完即結束呢?解決方案如下:
while true: #鏈結迴圈
conn,addr=phone.accept()
print('**線路是',conn)
print('客戶端的手機號是',addr)
while true: #通訊迴圈
try:
data=conn.recv(1024)
if not data:break
print('客戶端發來的訊息是',data)
conn.send(data.upper())
except exception:
break
conn.close()
phone.close()
注意:可能會有人遇到重啟服務端時address already in use 的情況,這個是由於你的服務端仍然存在四次揮手的timewait狀態在占用位址(如果不懂,請深入研究1.tcp三次握手,四次揮手 2.syn洪水攻擊 3.伺服器高併發情況下會有大量的timewait狀態的優化方法)
解決方法:
#加入一條socket配置,重用ip和埠
phone=socket(af_inet,sock_stream)
phone.setsockopt(sol_socket,so_reuseaddr,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))
網路程式設計 Socket程式設計
一 網路部分 1.ip 2.埠號 在網路協議中使用埠號識別主機上不同的程序,不同的埠對應於不同的服務 應用程式 3.協議 tcp二 socket部門socket通訊基本流程圖 根據socket通訊基本流程圖,總結通訊的基本步驟 伺服器端 第一步 建立乙個用於監聽連線的socket對像 第二步 用指定...
socket網路程式設計
首先認識乙個表示主機資訊的結構體 struct hostent h addrtype 這是表示主機所使用的位址型別的定義,在c語言winsock2.h標頭檔案中以 af 開頭的巨集定義就是它的值。如果使用的是ipv4,則值為 af inet 如果是ipv6,值為 af inet4 h length ...
Socket網路程式設計
socket 網路程式設計 在c free中建立乙個對話方塊工程,取名socket1,建立如下檔案結構 main.h ifndef main h define main h include bool winapi main proc hwnd hwnd,uint umsg,wparam wparam...