自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python中的Socket編程,全掌握!

開發(fā) 前端
Sockets 是組成當今網(wǎng)絡(luò)的各種通信協(xié)議,這些協(xié)議使得在兩個不同的程序或設(shè)備之間傳輸信息成為可能。例如,當我們打開瀏覽器時,我們作為客戶機就會創(chuàng)建與服務(wù)器的連接以傳輸信息。

在如今的互聯(lián)網(wǎng)當中,Socket 協(xié)議是最重要的基礎(chǔ)之一。本文涵蓋了在 Python 中處理 Socket 編程的所有領(lǐng)域。

圖片

為什么使用 Sockets

Sockets 是組成當今網(wǎng)絡(luò)的各種通信協(xié)議,這些協(xié)議使得在兩個不同的程序或設(shè)備之間傳輸信息成為可能。例如,當我們打開瀏覽器時,我們作為客戶機就會創(chuàng)建與服務(wù)器的連接以傳輸信息。

在深入研究這個通信原理之前,讓我們先弄清楚 Sockets 到底是什么。

什么是 Sockets

一般來說,Socket 是為發(fā)送和接收數(shù)據(jù)而構(gòu)建的內(nèi)部應(yīng)用協(xié)議。單個網(wǎng)絡(luò)將有兩個 Sockets,每個 Sockets 用于通信設(shè)備或程序,這些 Sockets 是IP地址和端口的組合。根據(jù)使用的端口號,單個設(shè)備可以有“n”個 Sockets,不同的端口可用于不同類型的協(xié)議。

下圖展示了一些常見端口號和相關(guān)協(xié)議的信息:

協(xié)議

端口號

Python 庫

應(yīng)用

HTTP

80

httplib,urllib,requests

網(wǎng)頁,網(wǎng)站

FTP

20

ftplib

文件傳輸

NNTP

119

nttplib

新聞傳輸

SMTP

25

smtplib

發(fā)送郵件

Telnet

23

telnetlib

命令行

POP3

110

poplib

接收郵件

Gopher

70

gopherlib

文檔傳輸

現(xiàn)在我們已經(jīng)了解了 Sockets 的概念,現(xiàn)在讓我們來看看 Python 的 Socket 模塊

如何在 Python 中實現(xiàn) Socket 編程

要在 Python 中實現(xiàn) Socket 編程,需要導(dǎo)入 socket 模塊。

該模塊的一些重要方法如下:

方法

描述

socket.socket()

用于創(chuàng)建 socket(服務(wù)器端和客戶端都需要創(chuàng)建)

socket.accept()

用于接受連接。它返回一對值(conn,address),其中conn是用于發(fā)送或接收數(shù)據(jù)的新 socket 對象,address是連接另一端的 socket 地址

socket.bind()

用于綁定到指定為參數(shù)的地址

socket.close()

用于關(guān)閉 socket

socket.connect()

用于連接到指定為參數(shù)的遠程地址

socket.listen()

使服務(wù)器能夠接受連接

現(xiàn)在我們已經(jīng)了解了 socket 模塊的重要性,接下來讓我們看看如何在 Python 中建服務(wù)器和客戶機。

什么是服務(wù)器

服務(wù)器或者是一個程序、一臺計算機,或者是一臺專門用于管理網(wǎng)絡(luò)資源的設(shè)備。服務(wù)器可以位于同一設(shè)備或計算機上,也可以本地連接到其他設(shè)備和計算機,甚至可以遠程連接。有各種類型的服務(wù)器,如數(shù)據(jù)庫服務(wù)器、網(wǎng)絡(luò)服務(wù)器、打印服務(wù)器等。

服務(wù)器通常使用socket.socket(),socket.bind(),socket.listen()等來建立連接并綁定到客戶端,現(xiàn)在讓我們編寫一個程序來創(chuàng)建服務(wù)器。

import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1234))
#port number can be anything between 0-65535(we usually specify non-previleged ports which are > 1023)
s.listen(5)

while True:
clt,adr=s.accept()
print(f"Connection to {adr}established")
#f string is literal string prefixed with f which
#contains python expressions inside braces
clt.send(bytes("Socket Programming in Python","utf-8 ")) #to send info to clientsocket

創(chuàng)建 socket 的第一個必要條件是導(dǎo)入相關(guān)模塊。之后是使用socket.socket()方法創(chuàng)建服務(wù)器端 socket。


AF_INET 是指來自 Internet 的地址,它需要一對(主機、端口),其中主機可以是某個特定網(wǎng)站的 URL 或其地址,端口號為整數(shù)。SOCK_STREAM 用于創(chuàng)建 TCP 協(xié)議。

bind()?方法接受兩個參數(shù)作為元組(主機、端口)。這里需要注意的是最好使用4位的端口號,因為較低的端口號通常被占用或者是系統(tǒng)預(yù)留的。listen()方法允許服務(wù)器接受連接,5是同時接受的多個連接的隊列。此處可以指定的最小值為0,如果未指定參數(shù),則采用默認的合適參數(shù)。

while?循環(huán)允許永遠接受連接,clt和adr?是客戶端對象和地址,print?語句只是打印出客戶端 socket 的地址和端口號,最后,clt.send用于以字節(jié)為單位發(fā)送數(shù)據(jù)。

現(xiàn)在我們的服務(wù)器已經(jīng)設(shè)置好了,讓我們繼續(xù)向客戶機前進。

什么是客戶端

客戶端是從服務(wù)器接收信息或服務(wù)的計算機或軟件。在客戶端-服務(wù)器模型中,客戶端從服務(wù)器請求服務(wù)。最好的例子是 Google Chrome、Firefox 等 Web 瀏覽器,這些 Web 瀏覽器根據(jù)用戶的指示請求 Web 服務(wù)器提供所需的網(wǎng)頁和服務(wù)。其他示例包括在線游戲、在線聊天等。

現(xiàn)在,讓我們看看如何用 Python 編程語言編寫客戶端程序:

import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
msg=s.recv(1024)
print(msg.decode("utf-8"))

首先依然是導(dǎo)入 socket 模塊,然后像創(chuàng)建服務(wù)器時那樣創(chuàng)建套接字。接著要在客戶端服務(wù)器之間創(chuàng)建連接,需要通過指定(host,port)使用 connect()方法。

注意:當客戶端和服務(wù)器位于同一臺計算機上時,需要使用gethostname。(LAN–localip/WAN–publicip)

在這里,客戶端希望從服務(wù)器接收一些信息,為此,我們需要使用recv()?方法,信息存儲在另一個變量msg中。需要注意的是正在傳遞的信息將以字節(jié)為單位,在上述程序的客戶端中,一次傳輸最多可以接收1024字節(jié)(緩沖區(qū)大?。?。根據(jù)傳輸?shù)男畔⒘?,可以將其指定為任意?shù)量。

最后,再解碼并打印正在傳輸?shù)南ⅰ?/p>

現(xiàn)在我們已經(jīng)了解了如何創(chuàng)建客戶端-服務(wù)器程序,接下來讓我們看看它們需要如何執(zhí)行。

客戶端服務(wù)器交互

要執(zhí)行這些程序,需要打開命令程序,進入創(chuàng)建客戶端和服務(wù)器程序的文件夾,然后鍵入:

py server.py #這里,server.py 是服務(wù)器的文件名

不出意外服務(wù)器開始運行

圖片

要執(zhí)行客戶端,需要打開另一個cmd窗口,然后鍵入:

py  client.py

圖片

下面讓我們將緩沖區(qū)大小減少到7,來看看相同的程序會怎么樣

圖片

如圖所示,傳輸7個字節(jié)后,連接終止。

其實這是一個問題,因為我們尚未收到完整的信息,但是連接卻提前關(guān)閉了,下面讓我們來解決這個問題。

多重通信

為了在客戶端收到完整信息之前繼續(xù)連接,我們可以使用while循環(huán)

import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2346))
while True:
msg=s.recv(7)
print(msg.decode("utf-8"))

如此修改之后,每次傳輸將以7個字節(jié)接收完整消息。

但這又引來了另一個問題,連接永遠不會終止,你永遠不知道什么時候會終止。此外,如果我們實際上不知道客戶端將從服務(wù)器接收到的消息或信息有多大,該怎么辦。在這種情況下,我們需要繼續(xù)完善代碼

complete_info=''
while True:
msg = s.recv(7)
if len(msg)<=0:
break
complete_info += msg.decode("utf-8")
print(complete_info)

在服務(wù)器端,使用close()方法,如下所示:

clt.close()

輸出如下:

圖片

程序會檢查信息的大小,并將其打印到一次兩個字節(jié)的緩沖區(qū)中,然后在完成連接后關(guān)閉連接。

傳輸 Python 對象

目前為止我們僅僅掌握了傳遞字符串的方法,但是,Python 中的 Socket 編程也允許我們傳輸 Python 對象。這些對象可以是集合、元組、字典等。要實現(xiàn)這一點,需要用到 Python 的 pickle 模塊。

Python pickle模塊

當我們實際序列化或反序列化 Python 中的對象時,就會使用到 Python pickle 模塊。讓我們看一個小例子

import pickle

mylist=[1,2,'abc']
mymsg = pickle.dumps(mylist)
print(mymsg)

Output:

b’x80x03]qx00(Kx01Kx02Xx03x00x00x00abcqx01e.’

在上面的程序中,mylist?是使用pickle模塊的dumps()?函數(shù)序列化的。還要注意,輸出以b開頭,表示它已轉(zhuǎn)換為字節(jié)。在 socket 編程中,可以實現(xiàn)此模塊以在客戶端和服務(wù)器之間傳輸 python 對象。

如何使用 pickle 模塊傳輸 Python 對象

當我們將 pickle 與 socket 一起使用時,完全可以通過網(wǎng)絡(luò)傳輸任何內(nèi)容。

先來看看服務(wù)端代碼

Server-Side:

import socket
import pickle

a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 2133)) #binding tuple
s.listen(5)
while True:
clt , adr = s.accept()
print(f"Connection to {adr}established")

m={1:"Client", 2:"Server"}
mymsg = pickle.dumps(m) #the msg we want to print later
mymsg = {len(mymsg):{a}}"utf-8") + mymsg
clt.send(mymsg)

這里,m?是一個字典,它基本上是一個需要從服務(wù)器發(fā)送到客戶端的 Python 對象。這是通過首先使用dumps()序列化對象,然后將其轉(zhuǎn)換為字節(jié)來完成的。

現(xiàn)在,讓我們記下客戶端:

Client-Side:

import socket
import pickle
a=10
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 2133))

while True:
complete_info = b''
rec_msg = True
while True:
mymsg = s.recv(10)
if rec_msg:
print(f"The length of message = {mymsg[:a]}")
x = int (mymsg[:a ] )
rec_msg = False
complete_info += mymsg
if len(complete_info)-a == x:
print("Recieved the complete info")
print(complete_info[a:])
m = pickle.loads(complete_info[a:])
print(m)
rec_msg = True
complete_info = b''
print(complete_info)

第一個while循環(huán)將幫助我們跟蹤完整的消息(complete_info)以及正在使用緩沖區(qū)接收的消息(rec_msg)。

然后,在接收消息時,我們所做的就是打印每一位消息,并將其放在大小為10的緩沖區(qū)中接收。此大小可以是任何大小,具體取決于個人選擇。

然后如果收到的消息等于完整消息,我們只會將消息打印為收到的完整信息,然后使用loads()反序列化消息。

輸出如下:

? 圖片 ?

責(zé)任編輯:武曉燕 來源: 蘿卜大雜燴
相關(guān)推薦

2024-04-23 13:36:00

2023-08-04 09:43:16

Socket編程Python

2010-03-03 16:19:29

Python Sock

2011-06-13 16:51:19

Qt Socket

2015-03-10 13:43:00

JavaSocket編程編程

2024-02-26 00:00:00

GoSocket編程

2013-09-22 11:03:20

SocketSocket編程

2016-11-04 21:37:16

PythonSocket

2012-03-19 11:41:30

JavaSocket

2011-06-20 13:43:08

Qt Socket 線程

2021-01-08 15:14:16

Python循環(huán)for循環(huán)

2010-03-17 13:46:55

Python sock

2023-10-26 15:49:53

Go日志

2013-03-26 12:46:23

Android開發(fā)So

2020-10-15 19:10:05

LinuxAPI函數(shù)

2013-03-27 13:26:04

Android開發(fā)Socket

2010-03-19 14:28:58

Java Socket

2009-06-11 10:00:05

Java Socket

2023-02-16 09:55:24

對象編程OOP

2023-07-06 08:31:50

Python對象編程
點贊
收藏

51CTO技術(shù)棧公眾號