1. 程式人生 > >python學習 網絡編程--socket

python學習 網絡編程--socket

bsp 封裝 str 表示 decode 位置 linux 斷開連接 關機

網絡通信標準---網絡協議
互聯網協議--osi七層協議
五層協議:應用層:應用層、表示層、會話層
傳輸層:傳輸層
網絡層:網絡層
數據鏈路層:數據鏈路層
物理層:物理層
物理層就是用來發送電信號的
數據鏈路層跑協議,分組標準。 ethernet以太網協議,規定電信號如何分組
電信號拿來後是一堆數據,只要規定了怎麽分組才能拿到正確數據
ethernet規定
一組電信號構成一個數據報,叫做幀
每一數據幀分成:報頭head和數據data兩部分
但凡接入互聯網必須要有網卡
每個網卡出廠都有自己的MAC地址 前六位廠商地址後幾位自己地址
MAC是全世界獨一無二的
以通訊角度來說,以太網協議有物理層和數據鏈路層已經可以實現通訊了
以太網有廣播的工作方式
廣播包只能在局域網裏面傳,要不數據量太大會造成網絡的故障
網絡層---ip協議 ipv4/ipv6
ip數據包也分成head和data部分 ip頭的意思和以太網差不多
ip地址和ip子網掩碼中間的運算得出一個地址,是網段地址
按位與運算 兩個同時是1才是1 二進制的ip地址和子網掩碼進行計算
按照這個網段地址找到範圍,然後再找到這個機器
ipv4/ipv6網關是用來幫助跨過子網的關口
跨子網,要用網關和網關進行通訊
用以太網的廣播方式將數據交給網關,但是得先獲得網關的MAC地址
但是我們知道的只有網關的IP地址
所以需要ARP協議,局域網內,用IP地址解析成MAC地址。這樣用網關的IP地址獲取MAC地址
才能將數據交給網關
如果發送端主機發送了目標MAC地址為FF.FF.FF.FF.FF.FF那麽它就知道發送端需要獲取MAC
但是接受數據的主機不知道是不是向它要MAC地址,所以還需要發送一個IP地址,讓他知道是自己需要的
ARP協議裏面的
同一子網地址內都用以太網的廣播方式
IP地址和MAC地址可以確定一個機器在什麽位置

-------------------------------------------------------------------------------------------------------------------------------------------

傳輸層跑兩種協議:tcp協議和udp協議得到端口 確定要傳輸的是這個機器的哪個軟件
ip加端口確定了全世界獨一無二的軟件
軟件用機器的哪個端口,65536個端口前1024是操作系統用,後面全是自己的軟件用
應用層:httpp ftp mai 協議 可以自己定協議
數據前一般都要加頭 然後是數據
DHCP :自動分配IP地址
DNS:域名服務 將網址域名地址解析成IP地址
tcp協議:
建立雙向連接,用來進行數據的交互相互發送。
工作方式:c傳給s一個請求,然後s再發送一個確認和一個請求,然後c再發送一個確認
所以一共發送了三次,三次握手
為了確認是否以我發送的那個數據,你倆進行回應,所以我的數據要加一個序列
如果你發送回來的時候我的序列+1證明是用我的數據進行回應
tcp協議又稱為可靠協議,發送完包一定要等待對方確認收到了我的包進行了回應,才算發成功
如果沒有回應過一段時間再發一次,所以是可靠協議。
可靠在發送完數據並不清空內存,直到對方回應確認收到後才收到
udp協議不用建立連接,被稱為不可靠協議,發送完數據就清空內存,不等對方的確認信息。
tcp有斷開連接,udp沒有
誰最後確認數據收到誰先斷,四次揮手斷鏈接

------------------------------------------------------------------------------------------------------------------------------------

socket編程:
應用層與運輸層之間多了一個socket抽象層
將傳輸協議都封裝好直接用
基於應用層與傳輸層之間的抽象層
用基於網絡的套接字:AF——INET
服務器端:先初始化socket(),然後與端口綁定bind()服務端的固定地址,對端口進行監聽listen()看誰來鏈接了
accept()阻塞直到有客戶端鏈接 和connect()組成一隊進行鏈接

import socket
socket.socket(socket.AF_INET,socket.SOCK_STREAM)
服務端:
import socket
#買手機
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 打開了這個服務端最後要關閉
#綁定手機卡
phone.bind((‘127.0.0.1‘,8080))#127.0.0.1指的就是自己這臺機器的IP地址
#開機
phone.listen(5)#5代表最大掛起的鏈接數
#等電話鏈接
conn,addr=phone.accept() 等待建立鏈接accept()等待建立
print(‘客戶端IP:%s,客戶端端口:%s‘%(addr[0],addr[1]))
data=conn.recv(1024) #最大收1024 recv()接受數據,括號內最大接收量
print(data.decode(‘utf-8‘))
conn.send(data.upper()) send()發送數據
#6、掛電話
conn.close() 建立的鏈接要關閉
#7.關機
phone.close()

客戶端:
import socket
#買手機
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 一樣打開這個端口
#綁定手機卡 客戶端沒必要綁定所以不用了
#開機 也不用監聽了

phone.connect((‘127.0.0.1‘,8080)) 主動建立鏈接,前面IP地址後面是端口
phone.send(‘hello‘.encode(‘utf-8‘)) 發送數據

data=phone.recv(1024)
print(data.decode(‘utf-8‘))
#關機
phone.close() 同樣要關機


持續性數據的交互,還有排隊的進行鏈接:
服務端:
import socket
#買手機
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#綁定手機卡
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((‘192.168.11.52‘,8080))#127.0.0.1指的就是自己這臺機器的IP地址
#開機
phone.listen(5)#5代表最大掛起的鏈接數
#等電話鏈接
print(‘starting...‘)
while True: #鏈接循環
conn,addr=phone.accept()
print(‘客戶端IP:%s,客戶端端口:%s‘%(addr[0],addr[1]))
while True: #通信循環
try: #用到try是因為有時候會發生但無法預知的錯誤
data=conn.recv(1024) #最大收1024
if not data:break #針對linux
print(data.decode(‘utf-8‘))
conn.send(data.upper())
except ConnectionResetError:
break
#6、掛電話
conn.close() #斷開連接
#7.關機
phone.close()

客戶端:

import socket
#買手機
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#綁定手機卡 客戶端沒必要綁定所以不用了
#開機 也不用監聽了
#等電話鏈接
phone.connect((‘192.168.11.52‘,8080))
while True:
msg=input(‘請輸入:‘).strip()
phone.send(msg.encode(‘utf-8‘))
data=phone.recv(1024)
print(data.decode(‘utf-8‘))
#關機
phone.close()

客戶端向服務端發送空消息的話 服務端的接收會卡住

python學習 網絡編程--socket