socket編程初識

複製代碼
1、socket
1、socket層



2、socket的理解
寫python代碼的時候socket就像是一個模塊,經過import導入,經過調用模塊中的方法創建兩個進程之間的鏈接和通訊。
Socket是應用層與傳輸層通訊的中間軟件抽象層,它是一組接口。它是爲了幫咱們簡化兩個進程之間通訊的步驟,
使用Socket不須要咱們很瞭解網絡層、數據鏈路層等底層的工做原理,Socket已經幫咱們把那些複雜的通訊過程封裝好了,
咱們直接去使用就好了

3、套接字(socket)的發展史
套接字起源於 20 世紀 70 年代加利福尼亞大學伯克利分校版本的 Unix,即人們所說的 BSD Unix。 所以,有時人們也把套接字稱爲「伯克利套接字」或「BSD 套接字」。
一開始,套接字被設計用在同 一臺主機上多個應用程序之間的通信。這也被稱進程間通信,或 IPC。
套接字有兩種(或者稱爲有兩個種族),分別是基於文件型的和基於網絡型的。 

基於文件類型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基於文件的套接字調用的就是底層的文件系統來取數據,兩個套接字進程運行在同一機器,能夠經過訪問同一個文件系統間接完成通訊


基於網絡類型的套接字家族
套接字家族的名字:AF_INET
(還有AF_INET6被用於ipv6,還有一些其餘的地址家族,不過,他們要麼是隻用於某個平臺,要麼就是已經被廢棄,或者是不多被使用,或者是根本沒有實現,
全部地址家族中,AF_INET是使用最普遍的一個,python支持不少種地址家族,可是因爲咱們只關心網絡編程,因此大部分時候我麼只使用AF_INET)



四、基於tcp/udp的socket
TCP:可靠的、面向鏈接的協議、傳輸效率低全雙工通訊(發送緩存&接收緩存)、面向字節流。使用TCP的應用:Web瀏覽器;電子郵件、文件傳輸程序。

UDP:不可靠的、無鏈接的服務,傳輸效率高,一對1、一對多、多對1、多對多、面向報文,盡最大努力服務,無擁塞控制。使用UDP的應用:域名系統 (DNS);視頻流;IP語音(VoIP)。




5、小例子
5-1、tcp協議的socket
對於TCP協議的socket server來講 不能同時接受多個client端的鏈接
# 服務端 import socket # 導入socket tcp_sk = socket.socket() # 實例化一個服務器對象 tcp_sk.bind(('127.0.0.1',8080)) # 服務器綁定一個IP地址和端口 tcp_sk.listen() # 監聽鏈接 # conn能夠理解爲在服務端中與客戶端進行交互的操做符(對象) # addr是客戶端的IP地址和端口 conn,addr = tcp_sk.accept() # 接受客戶端連接,此時若是沒有客戶端鏈接過來,服務器會在此等候,不會向下走(阻塞) while True: se_msg = input('>>>:') conn.send(se_msg.encode('utf-8')) # send發送的內容必須是bytes類型 re_msg = conn.recv(1024) # recv接收客戶端發送過來的內容,1024是接收的字節長度 print(re_msg.decode('utf-8')) conn.close() # 關閉與客戶端的鏈接 tcp_sk.close() # 關閉服務器 # 注意:通常狀況下服務器是不會關閉的,會一直爲用戶提供服務。 # 客戶端 import socket sk = socket.socket() # 實例化一個客戶端對象 sk.connect(('127.0.0.1',8080)) # 鏈接服務端的IP和端口 while True: re_msg = sk.recv(1024) print(re_msg.decode('utf-8')) se_msg = input('>>>:') sk.send(se_msg.encode('utf-8')) sk.close() # 關閉客戶端 注意:服務器和客戶端的send,recv是一一對應的,也就是說,服務器send一次,客戶端就須要recv一次, 客戶端send一次,服務端也要recv一次。 客戶端只須要鏈接上服務器就能夠了,客戶端的IP就是本身的IP,可是端口是由操做系統隨機分配的。 tcp是基於連接的,必須先啓動服務端,而後再啓動客戶端去連接服務端 還有的時候會遇到這種錯誤狀況:
錯誤的意思是說你這個端口被佔用了,引起的緣由多是由於,你運行服務端後直接按pycharm的強制退出鍵,致使操做系統並無 第一時間知道你已經結束了這個程序,若是不急用這個端口的話,你能夠等上幾分鐘,操做系統會反應過來你已經不須要這個程序了, 會自動幫你釋放這個端口,或者你能夠改一個端口使用,若是你很任性,你就要馬上立刻使用這個端口,那麼能夠這樣: 在bind以前加入一條socket配置,重用ip和端口 tcp_sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,
1) # 就是這個東西 tcp_sk.bind(('127.0.0.1',8080)) 可退出的: 服務端: import socket sk = socket.socket() sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8085)) sk.listen() while True: conn,addr = sk.accept() while True: se_msg = input('>>>:') conn.send(se_msg.encode('utf-8')) if se_msg == 'q': break re_msg = conn.recv(1024) if re_msg == b'q': break print(re_msg.decode('utf-8')) conn.close() sk.close 客戶端: import socket sk = socket.socket() sk.connect(('127.0.0.1',8085)) while True: re_msg = sk.recv(1024) if re_msg == b'q': break print(re_msg.decode('utf-8')) se_msg = input('>>>:') sk.send(se_msg.encode('utf-8')) if se_msg == 'q': break sk.close() 5-2、udp的socket
server端
import socket sk = socket.socket(type=socket.SOCK_DGRAM) # 設置type使其成爲udp類型的socket sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8005)) # 綁定IP和端口 msg,addr = sk.recvfrom(1024) # 接收信息和對方IP print(msg.decode('utf-8')) print(addr) sk.sendto('你好'.encode('utf-8'),addr) # 發送信息給對方 sk.close() client端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) sk.sendto('hello'.encode('utf-8'),('127.0.0.1',8005)) msg,addr = sk.recvfrom(1024) print(msg.decode('utf-8')) print(addr) sk.close() 注意:udp支持多個客戶端同時與服務端交互, 可是開始發送消息的一方確定是客戶端,由於客戶端不傳送消息給服務端,服務端是 不知道客戶端的IP的,是沒法通訊的,因此要通訊,只能客戶端先發起請求。 循環模式: 服務端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) # 設置type使其成爲udp類型的socket sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8005)) # 綁定IP和端口 while True: msg,addr = sk.recvfrom(1024) # 接收信息和對方IP print(addr,msg.decode('utf-8')) msg_send = input('>>>:') sk.sendto(msg_send.encode('utf-8'),addr) # 發送信息給對方 sk.close() 客戶端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) while True: msg_send = input('>>>:') sk.sendto(msg_send.encode('utf-8'),('127.0.0.1',8005)) msg,addr = sk.recvfrom(1024) print(addr,msg.decode('utf-8')) sk.close()

六、socket參數詳解
family 地址系列應爲AF_INET(默認值),AF_INET6,AF_UNIX,AF_CAN或AF_RDS。
(AF_UNIX 域其實是使用本地 socket 文件來通訊)
type 套接字類型應爲SOCK_STREAM(默認值),SOCK_DGRAM,SOCK_RAW或其餘SOCK_常量之一。
SOCK_STREAM 是基於TCP的,有保障的(即能保證數據正確傳送到對方)面向鏈接的SOCKET,多用於資料傳送。 
SOCK_DGRAM 是基於UDP的,無保障的面向消息的socket,多用於在網絡上發廣播信息。
proto 協議號一般爲零,能夠省略,或者在地址族爲AF_CAN的狀況下,協議應爲CAN_RAW或CAN_BCM之一。
fileno 若是指定了fileno,則其餘參數將被忽略,致使帶有指定文件描述符的套接字返回。
與socket.fromfd()不一樣,fileno將返回相同的套接字,而不是重複的。
這可能有助於使用socket.close()關閉一個獨立的插座。


2、軟件開發的架構
一、C/S架構:server client Client與Server就是客戶端與服務器端的意思,這裏的客戶端一般指的是咱們的應用程序 二、B/S架構 Browser與Server就是瀏覽器端與服務器端架構,Browser指的是瀏覽器,其實也是一種Client客戶端,只是這個客戶端不須要你們去安裝什麼應用程序, 只需在瀏覽器上經過HTTP請求服務器端相關的資源(網頁資源),客戶端Browser瀏覽器就能進行增刪改查。 三、b/s的趨勢 隨着咱們要安裝的應用程序愈來愈多,咱們就會感受很麻煩,若是能像瀏覽器同樣,只打開瀏覽器就能夠訪問各類資源,那麼久方便不少了, 因此手機端也是向着b/s方向發展的(微信小程序就是一個很好的例子,只要打開微信,在微信搜索須要的應用便可,不須要額外打開其餘程序) pc端 瀏覽器 統一了程序的入口 手機端 微信小程序 統一了程序的入口
複製代碼
相關文章
相關標籤/搜索