真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python網(wǎng)絡(luò)編程

Python網(wǎng)絡(luò)編程 一.網(wǎng)絡(luò)初識 IP地址 IP地址是指互聯(lián)網(wǎng)協(xié)議地址(英語:Internet Protocol Address,又譯為網(wǎng)際協(xié)議地址),是IP Address的縮寫 IP地址是IP協(xié)議提供的一種統(tǒng)一的地址格式,它為互聯(lián)網(wǎng)上的每一個網(wǎng)絡(luò)和每一臺主機分配一個邏輯地址,以此來屏蔽物理地址的差異 IP地址是一個32位的二進(jìn)制數(shù),通常被分割為4個“8位二進(jìn)制數(shù)”(也就是4個字節(jié)) IP地址通常用“點分十進(jìn)制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進(jìn)制整數(shù)

例:點分十進(jìn)IP地址(192.168.5.6),實際上是32位二進(jìn)制數(shù)(01100100.00000100.00000101.00000110)

10多年的蠡縣網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。營銷型網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整蠡縣建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)從事“蠡縣網(wǎng)站設(shè)計”,“蠡縣網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。端口(port) ”端口”是英文port的意譯,可以認(rèn)為是設(shè)備與外界通訊交流的出口 osi模型

套接字(socket)

Socket是應(yīng)用層與TCP/IP協(xié)議簇通信的中間軟件抽象層,它是一組接口。在設(shè)計模式中,Socket其實就是一個門面模式,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數(shù)據(jù),以符合指定的協(xié)議。

套接字家族 基于文件類型套接字家族的名字:AF_UNIX

unix一切皆文件,基于文件的套接字調(diào)用的就是底層的文件系統(tǒng)來取數(shù)據(jù),兩個套接字進(jìn)程運行在同一機器,可以通過訪問同一個文件系統(tǒng)間接完成通信

基于網(wǎng)絡(luò)類型套接字家族的名字:AF_INET

(還有AF_INET6被用于ipv6,還有一些其他的地址家族,不過,他們要么是只用于某個平臺,要么就是已經(jīng)被廢棄,或者是很少被使用,或者是根本沒有實現(xiàn),所有地址家族中,AF_INET是使用最廣泛的一個,python支持很多種地址家族,但是由于我們只關(guān)心網(wǎng)絡(luò)編程,所以大部分時候我么只使用AF_INET)

tcp協(xié)議、udp協(xié)議

TCP(Transmission Control Protocol)可靠的、面向連接的協(xié)議(eg:打電話)、傳輸效率低全雙工通信(發(fā)送緩存&接收緩存)、面向字節(jié)流。使用TCP的應(yīng)用:Web瀏覽器;電子郵件、文件傳輸程序。

UDP(User Datagram Protocol)不可靠的、無連接的服務(wù),傳輸效率高(發(fā)送前時延小),一對一、一對多、多對一、多對多、面向報文,盡努力服務(wù),無擁塞控制。使用UDP的應(yīng)用:域名系統(tǒng) (DNS);視頻流;IP語音(VoIP)

套接字(socket)初始使用 基于TCP協(xié)議的socket server端

import socket sk = socket.socket() sk.bind((\'127.0.0.1\', 8088)) sk.listen() conn, addr = sk.accept() while True: res = conn.recv(1024).decode(\'utf-8\') if res == \'bye\': break else: print(res) info = input(\'請輸入:n>>>\').encode(\'utf-8\') conn.send(info) conn.close() sk.close() client端

import socket sk= socket.socket() sk.connect((\'127.0.0.1\', 8088)) while True: info = input(\'請輸入:n>>>\').encode(\'utf-8\') sk.send(info) res = sk.recv(1024).decode(\'utf-8\') if res == \'bye\': break else: print(res) sk.close() 對于Address already in use的情況,可以加入socket配置重用ip和端口

import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加 sk.bind((\'127.0.0.1\',8898)) #把地址綁定到套接字 sk.listen() #監(jiān)聽鏈接 conn,addr = sk.accept() #接受客戶端鏈接 ret = conn.recv(1024) #接收客戶端信息 print(ret) #打印客戶端信息 conn.send(b\'hi\') #向客戶端發(fā)送信息 conn.close() #關(guān)閉客戶端套接字 sk.close() #關(guān)閉服務(wù)器套接字(可選) 一個服務(wù)端與多個客戶端交互示例

服務(wù)端

import socket sk = socket.socket() sk.bind((\'127.0.0.1\', 8088)) # listen([backlog])中的[backlog]參數(shù)代表服務(wù)端允許多少客戶端連接到服務(wù)端,即阻塞隊列長度,所以一共能與服務(wù)器連接的客戶端共有backlog+1個 sk.listen(3) while True: conn, addr = sk.accept() # sk.accept()放在循環(huán)內(nèi)部是為了每次與同一個客戶端交互結(jié)束后會重新建立conn連接,以便下一個客戶端連入 res = conn.recv(1024).decode(\'utf-8\') if res == \'bye\': break else: print(\'收到\',res) info = input(\'請輸入>>>\').encode(\'utf-8\') conn.send(info) conn.close() # 同上面sk.accept()的作用 sk.close()

客戶端(可以多個客戶端逐個與服務(wù)端進(jìn)行通訊)

import socket sk = socket.socket() sk.connect((\'127.0.0.1\', 8088)) while True: info = input(\'請輸入>>>\').encode(\'utf-8\') if info == \'bye\': break else: sk.send(info) res = sk.recv(1024).decode(\'utf-8\') print(res) sk.close() 基于UDP協(xié)議的socket:不可靠 無連接,效率高 server端

import socket ip_port=(\'127.0.0.1\',9000) BUFSIZE=1024 udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) udp_server_client.bind(ip_port) while True: msg,addr=udp_server_client.recvfrom(BUFSIZE) print(msg,addr) udp_server_client.sendto(msg.upper(),addr) client端

import socket ip_port=(\'127.0.0.1\',9000) BUFSIZE=1024 udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg=input(\'>>: \').strip() if not msg:continue udp_server_client.sendto(msg.encode(\'utf-8\'),ip_port) back_msg,addr=udp_server_client.recvfrom(BUFSIZE) print(back_msg.decode(\'utf-8\'),addr) 黏包

產(chǎn)生原因:粘包問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節(jié)的數(shù)據(jù)所造成的。

特點:只有TCP有粘包現(xiàn)象,UDP永遠(yuǎn)不會粘包

產(chǎn)生黏包的兩種情況 發(fā)送數(shù)據(jù)時間間隔很短,數(shù)據(jù)了很小,會合到一起,產(chǎn)生粘包

服務(wù)端

from socket import * ip_port=(\'127.0.0.1\',8080) tcp_socket_server=socket(AF_INET,SOCK_STREAM) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(5) conn,addr=tcp_socket_server.accept() data1=conn.recv(10) data2=conn.recv(10) print(\'----->\',data1.decode(\'utf-8\')) print(\'----->\',data2.decode(\'utf-8\')) conn.close()

客戶端

import socket BUFSIZE=1024 ip_port=(\'127.0.0.1\',8080) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) res=s.connect_ex(ip_port) s.send(\'hello\'.encode(\'utf-8\')) s.send(\'feng\'.encode(\'utf-8\')) 接收方不及時接收緩沖區(qū)的包,造成多個包接收(客戶端發(fā)送了一段數(shù)據(jù),服務(wù)端只收了一小部分,服務(wù)端下次再收的時候還是從緩沖區(qū)拿上次遺留的數(shù)據(jù),產(chǎn)生粘包)

服務(wù)端

from socket import * ip_port=(\'127.0.0.1\',8080) tcp_socket_server=socket(AF_INET,SOCK_STREAM) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(5) conn,addr=tcp_socket_server.accept() data1=conn.recv(2) #一次沒有收完整 data2=conn.recv(10)#下次收的時候,會先取舊的數(shù)據(jù),然后取新的 print(\'----->\',data1.decode(\'utf-8\')) print(\'----->\',data2.decode(\'utf-8\'))

客戶端

import socket BUFSIZE=1024 ip_port=(\'127.0.0.1\',8080) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) res=s.connect_ex(ip_port) s.send(\'hello feng\'.encode(\'utf-8\')) 黏包的解決方案 原理:問題的根源在于,接收端不知道發(fā)送端將要傳送的字節(jié)流的長度,所以解決粘包的方法就是圍繞,如何讓發(fā)送端在發(fā)送數(shù)據(jù)前,把自己將要發(fā)送的字節(jié)流總大小讓接收端知曉,然后接收端來一個死循環(huán)接收完所有數(shù)據(jù)。

直接告知客戶端發(fā)送數(shù)據(jù)的長度(Server端)

import socket, subprocess sk = socket.socket() sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sk.bind((\'localhost\', 8070)) sk.listen() while True: conn, addr = sk.accept() print(\'客戶端:\', addr) while True: msg = conn.recv(1024) if not msg: break res_temp = subprocess.Popen(msg.decode(\'utf-8\'), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) error = res_temp.stderr.read() if error: res = error else: res = res_temp.stdout.read() date_len = len(res) conn.send(str(date_len).encode(\'utf-8\')) data = conn.recv(1024).decode(\'utf-8\') if data == \'recv_ready\': conn.sendall() conn.close()

直接告知客戶端發(fā)送數(shù)據(jù)的長度(Client端)

import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) res = s.connect_ex((\'127.0.0.1\', 8080)) while True: msg = input(\'>>: \').strip() if len(msg) == 0: continue if msg == \'quit\': break s.send(msg.encode(\'utf-8\')) length = int(s.recv(1024).decode(\'utf-8\')) s.send(\'recv_ready\'.encode(\'utf-8\')) send_size = 0 recv_size = 0 data = b\'\' while recv_size < length: data += s.recv(1024) recv_size += len(data) print(data.decode(\'utf-8\'))

借助struct模塊打包定制報頭(Server端)

import socket, struct, json import subprocess sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 就是它,在bind前加 sk.bind((\'127.0.0.1\', 8080)) sk.listen(5) while True: conn, addr = sk.accept() while True: cmd = conn.recv(1024) if not cmd: break print(\'cmd: %s\' % cmd) res = subprocess.Popen(cmd.decode(\'utf-8\'), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) err = res.stderr.read() print(err) if err: back_msg = err else: back_msg = res.stdout.read() conn.send(struct.pack(\'i\', len(back_msg))) # 先發(fā)back_msg的長度 conn.sendall(back_msg) # 在發(fā)真實的內(nèi)容 conn.close()

借助struct模塊打包定制報頭(Server端)

import socket, time, struct s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) res = s.connect_ex((\'127.0.0.1\', 8080)) while True: msg = input(\'>>: \').strip() if len(msg) == 0: continue if msg == \'quit\': break s.send(msg.encode(\'utf-8\')) l = s.recv(4) x = struct.unpack(\'i\', l)[0] print(type(x), x) r_s = 0 data = b\'\' while r_s < x: r_d = s.recv(1024) data += r_d r_s += len(r_d) print(data.decode(\'gbk\')) # windows默認(rèn)gbk編碼 網(wǎng)絡(luò)傳輸大文件的解決方案 讀取固定字節(jié)內(nèi)容,避免全部讀進(jìn)內(nèi)存使得內(nèi)存占用過大

Server端

import json import socket import struct sk = socket.socket() sk.bind((\'127.0.0.1\',8090)) sk.listen() buffer = 1024 conn,addr = sk.accept() # 接收 head_len = conn.recv(4) head_len = struct.unpack(\'i\',head_len)[0] json_head = conn.recv(head_len).decode(\'utf-8\') head = json.loads(json_head) filesize = head[\'filesize\'] with open(head[\'filename\'],\'wb\') as f: while filesize: print(filesize) if filesize >= buffer: content = conn.recv(buffer) f.write(content) filesize -= len(content) else: content = conn.recv(filesize) f.write(content) break conn.close() sk.close()

Client端

import os import json import struct import socket sk = socket.socket() sk.connect((\'127.0.0.1\',8090)) buffer = 2048 # 發(fā)送文件 head = {\'filepath\':r\'C:UsersygDesktop\', \'filename\':r\'02 python fullstack s9day32 基于udp的socket服務(wù).mp4\', \'filesize\':None} file_path = os.path.join(head[\'filepath\'],head[\'filename\']) filesize = os.path.getsize(file_path) head[\'filesize\'] = filesize json_head = json.dumps(head) # 字典轉(zhuǎn)成了字符串 bytes_head = json_head.encode(\'utf-8\') # 字符串轉(zhuǎn)bytes # 計算head的長度 head_len = len(bytes_head) # 報頭的長度 pack_len = struct.pack(\'i\',head_len) sk.send(pack_len) # 先發(fā)報頭的長度 sk.send(bytes_head) # 再發(fā)送bytes類型的報頭 with open(file_path,\'rb\') as f: while filesize: print(filesize) if filesize >= buffer: content = f.read(buffer) # 每次讀出來的內(nèi)容 sk.send(content) filesize -= len(content) else: content = f.read(filesize) sk.send(content) break sk.close() socket方法

服務(wù)端套接字函數(shù)

s.bind() 綁定(主機,端口號)到套接字 s.listen() 開始TCP監(jiān)聽 s.accept() 被動接受TCP客戶的連接,(阻塞式)等待連接的到來

客戶端套接字函數(shù)

s.connect() 主動初始化TCP服務(wù)器連接 s.connect_ex() connect()函數(shù)的擴展版本,出錯時返回出錯碼,而不是拋出異常

公共用途的套接字函數(shù)

s.recv() 接收TCP數(shù)據(jù) s.send() 發(fā)送TCP數(shù)據(jù) s.sendall() 發(fā)送TCP數(shù)據(jù) s.recvfrom() 接收UDP數(shù)據(jù) s.sendto() 發(fā)送UDP數(shù)據(jù) s.getpeername() 連接到當(dāng)前套接字的遠(yuǎn)端的地址 s.getsockname() 當(dāng)前套接字的地址 s.getsockopt() 返回指定套接字的參數(shù) s.setsockopt() 設(shè)置指定套接字的參數(shù) s.close() 關(guān)閉套接字

面向鎖的套接字方法

s.setblocking() 設(shè)置套接字的阻塞與非阻塞模式 s.settimeout() 設(shè)置阻塞套接字操作的超時時間 s.gettimeout() 得到阻塞套接字操作的超時時間

面向文件的套接字的函數(shù)

s.fileno() 套接字的文件描述符 s.makefile() 創(chuàng)建一個與該套接字相關(guān)的文件 hmac模塊—客戶端鏈接合法性驗證 hmac模塊—客戶端鏈接合法性驗證

鏈接合法性驗證—舉例

服務(wù)端

# Server端 import os, socket, hmac secret_key = b\'secretkey\' sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) sk.bind((\'localhost\', 8889)) sk.listen() def check_client(conn): send_msg = os.urandom(32) conn.send(send_msg) h = hmac.new(secret_key, send_msg) digest = h.digest() client_digest = conn.recv(1024) return hmac.compare_digest(digest, client_digest) conn, addr = sk.accept() is_legal = check_client(conn) if is_legal: print(\'合法客戶端!\') conn.send(b\'legal\') while True: recv_msg = conn.recv(1024).decode(\'utf-8\') if recv_msg.lower() == \'q\': conn.send(b\'q\') conn.close() break else: print(recv_msg) info = input(\'服務(wù)端>>>\').strip() if info: conn.send(info.encode(\'utf-8\')) else: print(\'非法客戶端!\') conn.close() sk.close()

客戶端

#Client端 import socket, hmac secret_key = b\'secretkey\' sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) sk.connect((\'localhost\', 8889)) msg = sk.recv(1024) h = hmac.new(secret_key, msg) digest = h.digest() sk.send(digest) is_legal = sk.recv(1024) if is_legal == b\'legal\': while True: info = input(\'客戶端>>>\').strip() if info: sk.send(info.encode(\'utf-8\')) recv_msg = sk.recv(1024).decode(\'utf-8\') if recv_msg == \'q\': break else: print(recv_msg) sk.close() 利用socketserver模塊處理服務(wù)端與多客戶端交互問題

服務(wù)端

#Server端 import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): while True: recv_msg = self.request.recv(1024).decode(\'utf-8\') if recv_msg == \'q\': self.request.send(b\'q\') break else: print(recv_msg) info = input(\'服務(wù)端>>>\').strip() if info: self.request.send(info.encode(\'utf-8\')) if __name__ == \'__main__\': server = socketserver.ThreadingTCPServer((\'localhost\', 8889), MyServer) server.allow_reuse_address = True server.serve_forever()

客戶端

#Client端 import socket sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) sk.connect((\'localhost\', 8889)) while True: info = input(\'客戶端>>>\').strip() if info == \'\': continue elif info == \'q\': sk.send(info.encode(\'utf-8\')) break else: sk.send(info.encode(\'utf-8\')) recv_msg = sk.recv(1024).decode(\'utf-8\') print(recv_msg) sk.close()


當(dāng)前標(biāo)題:Python網(wǎng)絡(luò)編程
網(wǎng)站鏈接:http://weahome.cn/article/cpgggs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部