日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python黑帽编程2.8 套接字编程

發布時間:2025/3/15 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python黑帽编程2.8 套接字编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python黑帽編程2.8 套接字編程

套接字編程在本系列教程中地位并不是很突出,但是我們觀察網絡應用,絕大多數都是基于Socket來做的,哪怕是絕大多數的木馬程序也是如此。官方關于socket編程的文檔地址為https://docs.python.org/2/library/socket.html,我承認我看起來都很費勁。

套接字為BSD UNIX系統核心的一部分,而且他們也被許多其他類似UNIX的操作系統包括Linux所采納。許多非BSD UNIX系統(如ms-doswindowsos/2mac os及大部分主機環境)都以庫形式提供對套接字的支持。

三種最流行的套接字類型是:stream,datagramrawstreamdatagram套接字可以直接與TCP協議進行接口,而raw套接字則接口到IP協議。但套接字并不限于TCP/IP

Python 提供了兩個基本的套接字模塊:

l? 第一個是 socket,它提供了標準的 BSD Sockets API

l? 第二個是 socketServer 它提供了服務器中心類,可以簡化網絡服務器的開發。

本節課程主要關注socket模塊的使用。

2.8.1 socket函數

socket函數用來創建socket對象,使用前需要導入socket模塊。我們先看一下socket函數的使用方式:

socket.socket([family[, type[, proto]]])

我們看到socket函數接收三個參數,下面分別介紹:

family——套接字對象使用的地址族,可選值:AF_INET——IPv4地址族,AF_INET6——IPv6地址族,AF_UNIX——針對類UNIX系統的套接字,如圖2所示。

2

type可選參數如圖3所示。

3

proto是協議數,默認是0,通常不需要關心該參數。

熟悉了三個參數的含義,創建一個TCP或者UDPsocket對象就很容易了。

創建TCP Socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

創建UDP Socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

關于socket對象的各種方法的使用說明,大家可以去查官方文檔,我這里就不貼了,下面我們邊實踐,邊學習。

2.8.2 創建socket

我們首先來創建一個TCPsocket對象,代碼如下:

#Socket client example in python

import socket?? #for sockets

?

#create an AF_INET, STREAM socket (TCP)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket Created'

創建一個socket對象很簡單,第一步導入socket模塊,第二步使用socket.socket方法創建一個socket對象,參數在2.8.1節已經做了說明。運行結果如下:

4

2.8.3 客戶端編程

創建socket之后,現在我們看看如何創建client端,連接一個服務端,這里我們選擇知乎(www.zhihu.com)。socket類有個gethostbyname方法,可以用來把域名轉換為ip地址,例如:

import socket?? #for sockets

import sys? #for exit

?

try:

??? #create an AF_INET, STREAM socket (TCP)

??? s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

except socket.error, msg:

??? print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]

??? sys.exit();

?

print 'Socket Created'

?

host = 'www.zhihu.com'

?

try:

??? remote_ip = socket.gethostbyname( host )

except socket.gaierror:

??? #could not resolve

??? print 'Hostname could not be resolved. Exiting'

??? sys.exit()

????

print 'Ip address of ' + host + ' is ' + remote_ip

上面的代碼,我們首先導入了sys模塊,用于在出現異常的情況下調用sys.exit()退出。同時,完善了異常捕獲,創建socket可能會引發socket.error異常,gethostbyname方法可能會引發socket.gaierror異常,我們在編程過程中要注意這些錯誤。

運行結果如下:

5

現在我們獲得了ip,端口我們使用80,現在可以連接服務器了。

import socket?? #for sockets

import sys? #for exit

?

try:

??? #create an AF_INET, STREAM socket (TCP)

??? s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

except socket.error, msg:

??? print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]

??? sys.exit();

?

print 'Socket Created'

?

host = 'www.zhihu.com'

port = 80

?

try:

??? remote_ip = socket.gethostbyname( host )

?

except socket.gaierror:

??? #could not resolve

??? print 'Hostname could not be resolved. Exiting'

??? sys.exit()

????

print 'Ip address of ' + host + ' is ' + remote_ip

?

#Connect to remote server

s.connect((remote_ip , port))

?

print 'Socket Connected to ' + host + ' on ip ' + remote_ip

注意上面加粗的代碼,使用socket.connect方法連接服務端,參數為ip地址和端口。

連接上服務器之后,現在可以向服務器發送信息了。

我們在上面代碼的基礎上,添加下面的代碼:

#Send some data to remote server

message = "GET / HTTP/1.1\r\n\r\n"

?

try :

??? #Set the whole string

??? s.sendall(message)

except socket.error:

??? #Send failed

??? print 'Send failed'

??? sys.exit()

?

print 'Message send successfully'

首先定義了要發送的信息,準備發送一個http協議的get請求。隨后我們使用socket.sendall方法發送信息。信息發送之后,如果沒有異常產生,應該會得到知乎服務器的響應內容。那么如何接收信息呢?繼續添加如下代碼:

#Now receive data

reply = s.recv(4096)

?

print reply

我們使用socket.recv方法來接收數據,參數是接收的數據長度。現在我們來看一下運行結果:

6

最后,接收完數據之后,不要忘了關閉socket

s.close()

現在我們來總結下客戶端socket編程的基本流程:

1.????? 創建套接字

2.????? 連接服務端

3.????? 發送數據

4.????? 接收數據

5.????? 關閉連接

下面看一下,一個基本的服務端,要做哪些工作。

2.8.4 服務端編程

和客戶端編程類似,我們首先創建一個socket對象。

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

隨后,我們要把socket綁定到本機的IP和端口上。

try:

??? s.bind((HOST, PORT))

except socket.error , msg:

??? print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]

綁定ip和端口使用的是bind方法。

服務端不會主動連接其他主機,而是等待客戶端連接,這需要進入監聽狀態。

s.listen(10)

print 'Socket now listening'

listen方法接收一個參數,用來指定可以同時掛起的連接數。

監聽模式之后,如果有客戶端連接進來,如何接收連接呢?需要使用accept方法。

#wait to accept a connection - blocking call

conn, addr =s.accept()

accept方法會返回一個代表當前鏈接的connection對象和客戶端的ip地址。接下來就可以使用conn對象來接收和發送數據了,關閉連接也使用conn對象。

data = conn.recv(1024)

conn.sendall(data)

?

conn.close()

下面我們看一下服務端的完整代碼:

import socket

import sys

?

HOST = ''?? # Symbolic name meaning all available interfaces

PORT = 8888 # Arbitrary non-privileged port

?

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket created'

?

try:

??? s.bind((HOST, PORT))

except socket.error , msg:

??? print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]

??? sys.exit()

????

print 'Socket bind complete'

?

s.listen(10)

print 'Socket now listening'

#wait to accept a connection - blocking call

conn, addr = s.accept()

print 'Connected with ' + addr[0] + ':' + str(addr[1])

?

#now keep talking with the client

data = conn.recv(1024)

conn.sendall(data)

?

conn.close()

s.close()

將代碼保存為socket_server.py,從終端啟動,如下圖:

7

然后再啟動一個終端,使用telnet連接。

8

此時可以看到服務端打印了連接的客戶端,接下來咋telnet終端輸入字符,回車發送過去。結果如圖7

9

從圖7可以看到telnet終端顯示了服務端返回的信息。

2.8.5 改進服務端

作為服務端,只能接收一次連接,和客戶端進行有限次數的交互是不行的,要一直能接收來自客戶端的連接,下面我們改進服務端。

import socket

import sys

?

HOST = ''?? # Symbolic name meaning all available interfaces

PORT = 5000 # Arbitrary non-privileged port

?

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket created'

?

try:

??? s.bind((HOST, PORT))

except socket.error , msg:

??? print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]

??? sys.exit()

????

print 'Socket bind complete'

?

s.listen(10)

print 'Socket now listening'

?

#now keep talking with the client

while 1:

??? #wait to accept a connection - blocking call

??? conn, addr = s.accept()

??? print 'Connected with ' + addr[0] + ':' + str(addr[1])

????

??? data = conn.recv(1024)

??? reply = 'OK...' + data

??? if not data:

??????? break

????

??? conn.sendall(reply)

?

conn.close()

s.close()

修改后的代碼只是將接收客戶端連接的代碼放到一個while true循環里,這樣就可以不停的接收連接。保存上面的代碼,在終端打開等待連接,然后啟動三個終端使用telnet進行連接,結果如下:

10

這樣改起來,可以不停的接收新的連接了,但是每次只能接收一個連接,有新連接的時候,舊連接就會斷掉,還是不夠完美。想要分別對待每一個新入的連接,需要多線程登場了。

import socket

import sys

from thread import *

?

HOST = ''?? # Symbolic name meaning all available interfaces

PORT = 8888 # Arbitrary non-privileged port

?

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket created'

?

#Bind socket to local host and port

try:

??? s.bind((HOST, PORT))

except socket.error , msg:

??? print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]

??? sys.exit()

????

print 'Socket bind complete'

?

#Start listening on socket

s.listen(10)

print 'Socket now listening'

?

#Function for handling connections. This will be used to create threads

def clientthread(conn):

??? #Sending message to connected client

??? conn.send('Welcome to the server. Type something and hit enter\n') #send only takes string

????

??? #infinite loop so that function do not terminate and thread do not end.

??? while True:

????????

??????? #Receiving from client

??????? data = conn.recv(1024)

??????? reply = 'OK...' + data

??????? if not data:

??????????? break

????

??????? conn.sendall(reply)

????

??? #came out of loop

??? conn.close()

?

#now keep talking with the client

while 1:

??? #wait to accept a connection - blocking call

??? conn, addr = s.accept()

??? print 'Connected with ' + addr[0] + ':' + str(addr[1])

????

??? #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.

??? start_new_thread(clientthread ,(conn,))

?

s.close()

使用多線程,首先要導入thread模塊。隨后我們定義了一個名為clientthread的方法,該方法接收每個客戶端連接對象,在內部啟動一個新的while循環,這樣可以保證客戶端和服務端可以一直連接,反復通信。在外層,仍然保留while循環,每次有客戶端連接的時候,生成一個連接對象conn,然后使用thread模塊的start_new_thread方法啟動一個新的線程,新線程調用clientthread方法,傳入剛接收的客戶端連接對象。

我們將上面的代碼保存為socket_thread.py,然后從終端啟動,在啟動多個終端使用telnet進行連接,連接之后發消息測試,結果如下:

11

2.8.6 小結

本節我們學習了Pythonsocket的基本使用方法,并演示了基于TCP協議的客戶端和服務端編程方法。這里大家需要額外補充的知識點是多線程的使用,我們做網絡掃描、爬蟲等程序,都是離不開多線程應用的。

?

下一節是第二章的最后一節,和大家聊一聊面向對象編程思想及Python的面向對象編程方法。

2.8節《面向對象編程思想及Python的面向對象編程方法》已經在微信訂閱號搶先發布,心急的同學進入訂閱號(二維碼在下方),從菜單網絡安全”—>”Python黑帽編程進入即可。

?

查看完整系列教程,請關注我的微信訂閱號(xuanhun521,下方二維碼),回復“python”。問題討論請加qq群:Hacking 1群):303242737?? Hacking 2群):147098303

?

?

總結

以上是生活随笔為你收集整理的Python黑帽编程2.8 套接字编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。