版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
例11-1訪問TCP客戶端程序示例例11-1訪問TCP客戶端程序示例本例為訪問新浪網(wǎng)TCP客戶端程序示例。#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建一個socket對象s.connect(('',80))#建立與新浪網(wǎng)站的連接#發(fā)送數(shù)據(jù)請求s.send(b'GET/HTTP/1.1\r\nHost:\r\nConnection:close\r\n\r\n')#接收數(shù)據(jù)buffer=[]whileTrue:d=s.recv(1024)#每次最多接收服務(wù)器端1K字節(jié)數(shù)據(jù)ifd:#如果接收到數(shù)據(jù)buffer.append(d)#將字節(jié)串添加到列表中else:#返回空數(shù)據(jù),表示接收完畢,退出循環(huán)breakdata=b''.join(buffer)#將接收到的數(shù)據(jù)合并header,html=data.split(b'\r\n\r\n',1)#分離HTTP頭和HTML內(nèi)容print(header.decode('utf-8'))#打印HTTP頭部withopen('sina.html','wb')asf:#將接收的數(shù)據(jù)寫入文件f.write(html)在以上代碼中,首先創(chuàng)建一個基于TCP連接的Socket對象:#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建一個socket對象s.connect(('',80))#建立與新浪網(wǎng)站的連接代碼解釋:(1)導(dǎo)入模塊importsocket導(dǎo)入Python的socket模塊,用于創(chuàng)建和管理網(wǎng)絡(luò)連接。(2)創(chuàng)建socket對象s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)創(chuàng)建一個socket對象,用于建立TCP連接。參數(shù)說明如下:socket.AF_INET:指定使用IPv4地址族。socket.SOCK_STREAM:指定使用TCP協(xié)議。(3)建立連接s.connect(('',80))使用connect方法建立與新浪網(wǎng)站的連接。參數(shù)是一個元組,包含目標(biāo)服務(wù)器的域名和端口號(HTTP協(xié)議默認(rèn)端口為80)。(4)發(fā)送HTTP請求s.send(b'GET/HTTP/1.1\r\nHost:\r\nConnection:close\r\n\r\n')向服務(wù)器發(fā)送一個HTTPGET請求。請求內(nèi)容包括:GET/HTTP/1.1:請求的HTTP方法和版本。Host::請求的目標(biāo)主機(jī)名。Connection:close:請求完成后關(guān)閉連接。\r\n\r\n:表示請求頭的結(jié)束。請求內(nèi)容以字節(jié)串的形式發(fā)送,因此使用了b前綴。(5)接收數(shù)據(jù)buffer=[]whileTrue:d=s.recv(1024)#每次最多接收服務(wù)器端1K字節(jié)數(shù)據(jù)ifd:#如果接收到數(shù)據(jù)buffer.append(d)#將字節(jié)串添加到列表中else:#返回空數(shù)據(jù),表示接收完畢,退出循環(huán)breakdata=b''.join(buffer)#將接收到的數(shù)據(jù)合并創(chuàng)建一個空列表buffer,用于存儲接收到的數(shù)據(jù)。使用whileTrue循環(huán),通過recv方法接收數(shù)據(jù)。每次最多接收1024字節(jié)。如果接收到數(shù)據(jù)(d不為空),將其添加到buffer列表中。如果沒有接收到數(shù)據(jù)(d為空),表示數(shù)據(jù)接收完畢,退出循環(huán)。使用b''.join(buffer)將列表中的所有字節(jié)串合并為一個完整的字節(jié)串。(6)分離HTTP頭和HTML內(nèi)容header,html=data.split(b'\r\n\r\n',1)#分離HTTP頭和HTML內(nèi)容使用split方法將接收到的數(shù)據(jù)按b'\r\n\r\n'分割為兩部分:第一部分是HTTP響應(yīng)頭。第二部分是HTML內(nèi)容。split方法的第二個參數(shù)1表示最多分割一次,確保只分割出兩部分。(7)打印HTTP頭部print(header.decode('utf-8'))#打印HTTP頭部使用decode('utf-8')將字節(jié)串header解碼為字符串,以便打印。打印出HTTP響應(yīng)頭的內(nèi)容。(8)將HTML內(nèi)容保存到文件withopen('sina.html','wb')asf:#將接收的數(shù)據(jù)寫入文件f.write(html)使用withopen語句以二進(jìn)制寫入模式('wb')打開一個文件'sina.html'。使用write方法將HTML內(nèi)容(字節(jié)串)寫入文件。例11-2簡單的TCP服務(wù)器程序示例本例為簡單的TCP服務(wù)器程序示例(該程序接收客戶端的連接,將客戶端發(fā)送的字符串加上"Hello"后再發(fā)回給客戶端)。#coding=gbkimportsocket#導(dǎo)入socket模塊importthreading#導(dǎo)入threading模塊deftcplink(sock,addr):print('接收到來自%s:%s的連接請求'%addr)sock.send(b'Welcome!')#向客戶端發(fā)送歡迎信息whileTrue:data=sock.recv(1024)#接收客戶端發(fā)來的信息ifnotdataordata.decode('utf-8')=='exit':#如果沒有數(shù)據(jù)或收到'exit'信息break#終止循環(huán)#將收到的信息加上"Hello"后發(fā)送回去sock.send(('Hello,%s!'%data.decode('utf-8')).encode('utf-8'))sock.close()#關(guān)閉連接print('來自%s:%s的連接已關(guān)閉.'%addr)#創(chuàng)建一個基于IPv4和TCP協(xié)議的Sockets=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.bind(('',8888))#監(jiān)聽本機(jī)8888端口s.listen(5)#最大連接數(shù)為5print('等待客戶端連接...')whileTrue:sock,addr=s.accept()#接受一個新連接#創(chuàng)建新線程來處理TCP連接t=threading.Thread(target=tcplink,args=(sock,addr))t.start()程序首先創(chuàng)建一個基于IPv4和TCP協(xié)議的Socket,如下所示:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)接下來,需要綁定監(jiān)聽的地址和端口。服務(wù)器可能有多塊網(wǎng)卡,可以選擇綁定到某一塊網(wǎng)卡的IP地址,也可以使用來綁定所有網(wǎng)絡(luò)地址,或者使用來綁定本機(jī)地址。是一個特殊的IP地址,表示本機(jī)地址。如果服務(wù)器綁定到這個地址,則客戶端必須在本機(jī)上運(yùn)行才能連接,外部計(jì)算機(jī)無法訪問。端口號需要提前指定。由于我們編寫的服務(wù)不是標(biāo)準(zhǔn)服務(wù),因此選擇使用8888作為端口號。請注意,端口號小于1024的情況下,綁定時(shí)需要具有管理員權(quán)限。s.bind(('',8888))#監(jiān)聽本機(jī)8888端口接著,調(diào)用listen()方法開始監(jiān)聽端口,同時(shí)傳入的參數(shù)指定等待連接的最大數(shù)量為5:s.listen(5)#最大連接數(shù)為5print('等待客戶端連接...')接下來,服務(wù)器程序通過一個無限循環(huán)來接受來自客戶端的連接。accept()方法會阻塞并返回一個客戶端的連接。whileTrue:sock,addr=s.accept()#接受一個新連接#創(chuàng)建新線程來處理TCP連接t=threading.Thread(target=tcplink,args=(sock,addr))t.start()每個連接都必須創(chuàng)建一個新線程(或進(jìn)程)來處理,否則單線程在處理某個連接的過程中將無法接受其他客戶端的連接。deftcplink(sock,addr):print('接收到來自%s:%s的連接請求'%addr)sock.send(b'Welcome!')#向客戶端發(fā)送歡迎信息whileTrue:data=sock.recv(1024)#接收客戶端發(fā)來的信息ifnotdataordata.decode('utf-8')=='exit':#如果沒有數(shù)據(jù)或收到'exit'信息break#終止循環(huán)#將收到的信息加上"Hello"后發(fā)送回去sock.send(('Hello,%s!'%data.decode('utf-8')).encode('utf-8'))sock.close()#關(guān)閉連接print('來自%s:%s的連接已關(guān)閉.'%addr)連接建立后,服務(wù)器首先發(fā)送一條歡迎消息,然后等待客戶端發(fā)送數(shù)據(jù),并在發(fā)送回復(fù)時(shí)加上Hello。如果客戶端發(fā)送了exit字符串,服務(wù)器將直接關(guān)閉連接。為了測試這個服務(wù)器程序,還需要編寫一個客戶端程序:#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(('',8888))#建立連接print(s.recv(1024).decode('utf-8'))#打印接收到的歡迎消息fordatain[b'AA',b'BB',b'CC']:s.send(data)#客戶端程序發(fā)送人名數(shù)據(jù)給服務(wù)器print(s.recv(1024).decode('utf-8'))#打印服務(wù)器的回復(fù)s.send(b'exit')#發(fā)送退出信號s.close()#關(guān)閉連接同時(shí)打開兩個命令行窗口,一個運(yùn)行服務(wù)器程序,另一個運(yùn)行客戶端程序,這樣就可以看到程序運(yùn)行效果,如圖11-2和圖11-3所示。圖11-2服務(wù)器程序圖11-3客戶端程序需要注意的是,客戶端程序在運(yùn)行完成后會自動退出,而服務(wù)器程序則會持續(xù)運(yùn)行,直到按下Ctrl+C鍵退出。為訪問新浪網(wǎng)TCP客戶端程序示例。#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建一個socket對象s.connect(('',80))#建立與新浪網(wǎng)站的連接#發(fā)送數(shù)據(jù)請求s.send(b'GET/HTTP/1.1\r\nHost:\r\nConnection:close\r\n\r\n')#接收數(shù)據(jù)buffer=[]whileTrue:d=s.recv(1024)#每次最多接收服務(wù)器端1K字節(jié)數(shù)據(jù)ifd:#如果接收到數(shù)據(jù)buffer.append(d)#將字節(jié)串添加到列表中else:#返回空數(shù)據(jù),表示接收完畢,退出循環(huán)breakdata=b''.join(buffer)#將接收到的數(shù)據(jù)合并header,html=data.split(b'\r\n\r\n',1)#分離HTTP頭和HTML內(nèi)容print(header.decode('utf-8'))#打印HTTP頭部withopen('sina.html','wb')asf:#將接收的數(shù)據(jù)寫入文件f.write(html)在以上代碼中,首先創(chuàng)建一個基于TCP連接的Socket對象:#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建一個socket對象s.connect(('',80))#建立與新浪網(wǎng)站的連接代碼解釋:(1)導(dǎo)入模塊importsocket導(dǎo)入Python的socket模塊,用于創(chuàng)建和管理網(wǎng)絡(luò)連接。(2)創(chuàng)建socket對象s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)創(chuàng)建一個socket對象,用于建立TCP連接。參數(shù)說明如下:socket.AF_INET:指定使用IPv4地址族。socket.SOCK_STREAM:指定使用TCP協(xié)議。(3)建立連接s.connect(('',80))使用connect方法建立與新浪網(wǎng)站的連接。參數(shù)是一個元組,包含目標(biāo)服務(wù)器的域名和端口號(HTTP協(xié)議默認(rèn)端口為80)。(4)發(fā)送HTTP請求s.send(b'GET/HTTP/1.1\r\nHost:\r\nConnection:close\r\n\r\n')向服務(wù)器發(fā)送一個HTTPGET請求。請求內(nèi)容包括:GET/HTTP/1.1:請求的HTTP方法和版本。Host::請求的目標(biāo)主機(jī)名。Connection:close:請求完成后關(guān)閉連接。\r\n\r\n:表示請求頭的結(jié)束。請求內(nèi)容以字節(jié)串的形式發(fā)送,因此使用了b前綴。(5)接收數(shù)據(jù)buffer=[]whileTrue:d=s.recv(1024)#每次最多接收服務(wù)器端1K字節(jié)數(shù)據(jù)ifd:#如果接收到數(shù)據(jù)buffer.append(d)#將字節(jié)串添加到列表中else:#返回空數(shù)據(jù),表示接收完畢,退出循環(huán)breakdata=b''.join(buffer)#將接收到的數(shù)據(jù)合并創(chuàng)建一個空列表buffer,用于存儲接收到的數(shù)據(jù)。使用whileTrue循環(huán),通過recv方法接收數(shù)據(jù)。每次最多接收1024字節(jié)。如果接收到數(shù)據(jù)(d不為空),將其添加到buffer列表中。如果沒有接收到數(shù)據(jù)(d為空),表示數(shù)據(jù)接收完畢,退出循環(huán)。使用b''.join(buffer)將列表中的所有字節(jié)串合并為一個完整的字節(jié)串。(6)分離HTTP頭和HTML內(nèi)容header,html=data.split(b'\r\n\r\n',1)#分離HTTP頭和HTML內(nèi)容使用split方法將接收到的數(shù)據(jù)按b'\r\n\r\n'分割為兩部分:第一部分是HTTP響應(yīng)頭。第二部分是HTML內(nèi)容。split方法的第二個參數(shù)1表示最多分割一次,確保只分割出兩部分。(7)打印HTTP頭部print(header.decode('utf-8'))#打印HTTP頭部使用decode('utf-8')將字節(jié)串header解碼為字符串,以便打印。打印出HTTP響應(yīng)頭的內(nèi)容。(8)將HTML內(nèi)容保存到文件withopen('sina.html','wb')asf:#將接收的數(shù)據(jù)寫入文件f.write(html)使用withopen語句以二進(jìn)制寫入模式('wb')打開一個文件'sina.html'。使用write方法將HTML內(nèi)容(字節(jié)串)寫入文件。例11-3訪問TCP客戶端程序示例本例為訪問新浪網(wǎng)TCP客戶端程序示例。#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建一個socket對象s.connect(('',80))#建立與新浪網(wǎng)站的連接#發(fā)送數(shù)據(jù)請求s.send(b'GET/HTTP/1.1\r\nHost:\r\nConnection:close\r\n\r\n')#接收數(shù)據(jù)buffer=[]whileTrue:d=s.recv(1024)#每次最多接收服務(wù)器端1K字節(jié)數(shù)據(jù)ifd:#如果接收到數(shù)據(jù)buffer.append(d)#將字節(jié)串添加到列表中else:#返回空數(shù)據(jù),表示接收完畢,退出循環(huán)breakdata=b''.join(buffer)#將接收到的數(shù)據(jù)合并header,html=data.split(b'\r\n\r\n',1)#分離HTTP頭和HTML內(nèi)容print(header.decode('utf-8'))#打印HTTP頭部withopen('sina.html','wb')asf:#將接收的數(shù)據(jù)寫入文件f.write(html)在以上代碼中,首先創(chuàng)建一個基于TCP連接的Socket對象:#coding=gbkimportsocket#導(dǎo)入socket模塊s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建一個socket對象s.connect(('',80))#建立與新浪網(wǎng)站的連接代碼解釋:(1)導(dǎo)入模塊importsocket導(dǎo)入Python的socket模塊,用于創(chuàng)建和管理網(wǎng)絡(luò)連接。(2)創(chuàng)建socket對象s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)創(chuàng)建一個socket對象,用于建立TCP連接。參數(shù)說明如下:socket.AF_INET:指定使用IPv4地址族。socket.SOCK_STREAM:指定使用TCP協(xié)議。(3)建立連接s.connect(('',80))使用connect方法建立與新浪網(wǎng)站的連接。參數(shù)是一個元組,包含目標(biāo)服務(wù)器的域名和端口號(HTTP協(xié)議默認(rèn)端口為80)。(4)發(fā)送HTTP請求s.send(b'GET/HTTP/1.1\r\nHost:\r\nConnection:close\r\n\r\n')向服務(wù)器發(fā)送一個HTTPGET請求。請求內(nèi)容包括:GET/HTTP/1.1:請求的HTTP方法和版本。Host::請求的目標(biāo)主機(jī)名。Connection:close:請求完成后關(guān)閉連接。\r\n\r\n:表示請求頭的結(jié)束。請求內(nèi)容以字節(jié)串的形式發(fā)送,因此使用了b前綴。(5)接收數(shù)據(jù)buffer=[]whileTrue:d=s.recv(1024)#每次最多接收服務(wù)器端1K字節(jié)數(shù)據(jù)ifd:#如果接收到數(shù)據(jù)buffer.append(d)#將字節(jié)串添加到列表中else:#返回空數(shù)據(jù),表示接收完畢,退出循環(huán)breakdata=b''.join(buffer)#將接收到的數(shù)據(jù)合并創(chuàng)建一個空列表buffer,用于存儲接收到的數(shù)據(jù)。使用whileTrue循環(huán),通過recv方法接收數(shù)據(jù)。每次最多接收1024字節(jié)。如果接收到數(shù)據(jù)(d不為空),將其添加到buffer列表中。如果沒有接收到數(shù)據(jù)(d為空),表示數(shù)據(jù)接收完畢,退出循環(huán)。使用b''.join(buffer)將列表中的所有字節(jié)串合并為一個完整的字節(jié)串。(6)分離HTTP頭和HTML內(nèi)容header,html=data.split(b'\r\n\r\n',1)#分離HTTP頭和HTML內(nèi)容使用split方法將接收到的數(shù)據(jù)按b'\r\n\r\n'分割為兩部分:第一部分是HTTP響應(yīng)頭。第二部分是HTML內(nèi)容。split方法的第二個參數(shù)1表示最多分割一次,確保只分割出兩部分。(7)打印HTTP頭部print(header.decode('utf-8'))#打印HTTP頭部使用decode('utf-8')將字節(jié)串header解碼為字符串,以便打印。打印出HTTP響應(yīng)頭的內(nèi)容。(8)將HTML內(nèi)容保存到文件withopen('sina.html','wb')asf:#將接收的數(shù)據(jù)寫入文件f.write(html)使用withopen語句以二進(jìn)制寫入模式('wb')打開一個文件'sina.html'。使用write方法將HTML內(nèi)容(字節(jié)串)寫入文件。例11-4網(wǎng)絡(luò)嗅探器程序示例本例為網(wǎng)絡(luò)嗅探器程序示例(以下代碼將在運(yùn)行60秒后,輸出本機(jī)所在局域網(wǎng)內(nèi)非本機(jī)發(fā)出的數(shù)據(jù)包,并統(tǒng)計(jì)來自不同主機(jī)的數(shù)據(jù)包數(shù)量。有關(guān)多線程的詳細(xì)信息,請參本書相關(guān)章節(jié)的介紹)。#coding=gbkimportsocketimportthreadingimporttimeactive_degree=dict()flag=1lock=threading.Lock()#添加線程鎖defmain():globalactive_degreeglobalflagHOST=socket.gethostbyname(socket.gethostname())s=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_IP)s.bind((HOST,0))s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)s.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)try:whileflag:c=s.recvfrom(65565)host=c[1][0]withlock:#使用線程鎖保護(hù)對共享資源的訪問active_degree[host]=active_degree.get(host,0)+1ifhost!='':#假設(shè)的當(dāng)前主機(jī)IPprint(c)finally:#確保在退出時(shí)禁用混雜模式并關(guān)閉套接字s.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)s.close()t=threading.Thread(target=main)t.start()time.sleep(60)flag=0t.join()foriteminactive_degree.items():print(item)代碼解釋:(1)導(dǎo)入模塊importsocketimportthreadingimporttime導(dǎo)入所需的模塊:socket:用于網(wǎng)絡(luò)通信。threading:用于多線程操作。time:用于時(shí)間相關(guān)的操作。(2)定義全局變量active_degree=dict()flag=1lock=threading.Lock()active_degree:一個字典,用于存儲每個源IP地址的活躍度(即捕獲到的數(shù)據(jù)包數(shù)量)。flag:一個全局標(biāo)志,用于控制主循環(huán)的運(yùn)行狀態(tài)。lock:一個線程鎖,用于保護(hù)對共享資源(active_degree字典)的訪問,避免多線程環(huán)境下的數(shù)據(jù)競爭問題。(3)定義主函數(shù)defmain():globalactive_degreeglobalflag定義主函數(shù)main,并聲明使用全局變量active_degree和flag。(4)獲取本地主機(jī)名和IP地址HOST=socket.gethostbyname(socket.gethostname())使用socket.gethostname()獲取本地主機(jī)名,然后通過socket.gethostbyname()將其轉(zhuǎn)換為IP地址。(5)創(chuàng)建原始套接字s=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_IP)s.bind((HOST,0))s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)s.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)創(chuàng)建一個原始套接字(socket.SOCK_RAW),用于捕獲所有經(jīng)過本地網(wǎng)絡(luò)接口的IP數(shù)據(jù)包。將套接字綁定到本地主機(jī)的IP地址和端口0。設(shè)置套接字選項(xiàng)IP_HDRINCL,表示IP頭包含在數(shù)據(jù)包中。使用ioctl啟用混雜模式(RCVALL_ON),使套接字能夠捕獲所有經(jīng)過網(wǎng)絡(luò)接口的數(shù)據(jù)包。(6)數(shù)據(jù)包捕獲和處理try:whileflag:c=s.recvfrom(65565)host=c[1][0]withlock:active_degree[host]=active_degree.get(host,0)+1ifhost!='':#假設(shè)的當(dāng)前主機(jī)IPprint(c)finally:s.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)s.close()使用try...finally結(jié)構(gòu)確保在程序退出時(shí)能夠正確關(guān)閉套接字并禁用混雜模式。在whileflag循環(huán)中,持續(xù)捕獲數(shù)據(jù)包:使用recvfrom方法接收數(shù)據(jù)包,最大長度為65565字節(jié)。提取數(shù)據(jù)包的源IP地址(host)。使用線程鎖(withlock)保護(hù)對active_degree字典的訪問,避免多線程環(huán)境下的數(shù)據(jù)競爭。更新active_degree字典中對應(yīng)IP地址的活躍度計(jì)數(shù)。如果源IP地址不是本地主機(jī)的IP地址(假設(shè)為),則打印捕獲的數(shù)據(jù)包內(nèi)容。(7)創(chuàng)建并啟動線程t=threading.Thread(target=main)t.start()time.sleep(60)flag=0t.join()創(chuàng)建一個線程t,目標(biāo)函數(shù)為main。啟動線程start()。等待60秒(time.sleep(60)),然后將flag設(shè)置為0,通知主循環(huán)停止。使用join()方法等待線程結(jié)束。(8)輸出統(tǒng)計(jì)結(jié)果foriteminactive_degree.items():print(item)遍歷active_degree字典,打印每個IP地址及其對應(yīng)的活躍度計(jì)數(shù)。例11-5端口掃描器程序示例本例為端口掃描器程序示例。#coding=gbkimportsocketimportmultiprocessingdefget_ports_service():"""獲取常用端口對應(yīng)的服務(wù)名稱"""ports_service={}forportinlist(range(1,100))+[143,145,113,443,445,3389,8080]:try:ports_service[port]=socket.getservbyport(port)exceptsocket.error:ports_service[port]="未知服務(wù)"returnports_servicedefscan_ports(host,ports_service):"""掃描指定主機(jī)的開放端口"""open_ports=[]forportinports_service:sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.settimeout(0.01)#設(shè)置超時(shí)時(shí)間try:#嘗試連接指定端口sock.connect((host,port))#記錄打開的端口open_ports.append(port)exceptsocket.error:passfinally:sock.close()#確保socket被關(guān)閉returnopen_portsif__name__=='__main__':#獲取端口服務(wù)信息ports_service=get_ports_service()#創(chuàng)建進(jìn)程池,允許最多8個進(jìn)程同時(shí)運(yùn)行pool=multiprocessing.Pool(processes=8)network='10.2.1.'results=[]forhost_numberinrange(0,10):host=network+str(host_number)#創(chuàng)建一個新進(jìn)程,同時(shí)記錄其運(yùn)行結(jié)果result=pool.apply_async(scan_ports,(host,ports_service))results.append((host,result))#將結(jié)果和主機(jī)一起存儲print(f'正在掃描:{host}...')#關(guān)閉進(jìn)程池,close()必須在join()之前調(diào)用pool.close()#等待進(jìn)程池中的進(jìn)程全部執(zhí)行結(jié)束pool.join()#打印輸出結(jié)果forhost,resultinresults:print(f'主機(jī):{host}')forportinresult.get():print(f'開放端口:{port};服務(wù):{ports_service[port]}')返回結(jié)果:正在掃描:...正在掃描:...…主機(jī):開放端口:25;服務(wù):smtp主機(jī):…代碼解釋:(1)導(dǎo)入模塊importsocketimportmultiprocessingsocket模塊用于處理網(wǎng)絡(luò)通信,包括創(chuàng)建套接字(Socket)和進(jìn)行網(wǎng)絡(luò)連接。multiprocessing模塊用于創(chuàng)建多進(jìn)程,以提高程序的并發(fā)執(zhí)行能力。(2)獲取端口服務(wù)名稱defget_ports_service():"""獲取常用端口對應(yīng)的服務(wù)名稱"""ports_service={}forportinlist(range(1,100))+[143,145,113,443,445,3389,8080]:try:ports_service[port]=socket.getservbyport(port)exceptsocket.error:ports_service[port]="未知服務(wù)"returnports_service功能:該函數(shù)用于獲取常用端口對應(yīng)的服務(wù)名稱。邏輯:定義一個空字典ports_service,用于存儲端口號和服務(wù)名稱的映射。遍歷一個端口列表,包括1到99的所有端口,以及一些特定的常用端口(如143、145、113、443、445、3389和8080)。使用socket.getservbyport(port)嘗試獲取每個端口對應(yīng)的服務(wù)名稱。如果成功,將端口號和服務(wù)名稱添加到字典中;如果失?。⊕伋鰏ocket.error異常),則將該端口的服務(wù)名稱設(shè)置為“未知服務(wù)”。返回包含端口號和服務(wù)名稱映射的字典。(3)掃描指定主機(jī)的開放端口defscan_ports(host,ports_service):"""掃描指定主機(jī)的開放端口"""open_ports=[]forportinports_service:sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.settimeout(0.01)#設(shè)置超時(shí)時(shí)間try:#嘗試連接指定端口sock.connect((host,port))#記錄打開的端口open_ports.append(port)exceptsocket.error:passfinally:sock.close()#確保socket被關(guān)閉returnopen_ports功能:該函數(shù)用于掃描指定主機(jī)的開放端口。邏輯:定義一個空列表open_ports,用于存儲開放的端口。遍歷ports_service字典中的所有端口。對于每個端口:①創(chuàng)建一個TCP套接字(socket.AF_INET表示IPv4,socket.SOCK_STREAM表示TCP)。②設(shè)置超時(shí)時(shí)間為0.01秒,以避免長時(shí)間等待連接。③嘗試使用sock.connect((host,port))連接到目標(biāo)主機(jī)的指定端口。④如果連接成功(沒有拋出異常),則將該端口添加到open_ports列表中。⑤如果連接失敗(拋出socket.error異常),則忽略該端口。⑥無論成功或失敗,最終都會關(guān)閉套接字。返回包含開放端口的列表。(5)主程序邏輯if__name__=='__main__':#獲取端口服務(wù)信息ports_service=get_ports_service()#創(chuàng)建進(jìn)程池,允許最多8個進(jìn)程同時(shí)運(yùn)行pool=multiprocessing.Pool(processes=8)network='10.2.1.'results=[]forhost_numberinrange(0,10):host=network+str(host_number)#創(chuàng)建一個新進(jìn)程,同時(shí)記錄其運(yùn)行結(jié)果result=pool.apply_async(scan_ports,(host,ports_service))results.append((host,result))#將結(jié)果和主機(jī)一起存儲print(f'正在掃描:{host}...')#關(guān)閉進(jìn)程池,close()必須在join()之前調(diào)用pool.close()#等待進(jìn)程池中的進(jìn)程全部執(zhí)行結(jié)束pool.join()#打印輸出結(jié)果forhost,resultinresults:print(f'主機(jī):{host}')forportinresult.get():print(f'開放端口:{port};服務(wù):{ports_service[port]}')功能:主程序用于掃描指定網(wǎng)絡(luò)范圍內(nèi)的主機(jī)開放的端口,并打印結(jié)果。邏輯:調(diào)用get_ports_service()函數(shù)獲取端口服務(wù)信息。創(chuàng)建一個進(jìn)程池,允許最多8個進(jìn)程同時(shí)運(yùn)行,用于并發(fā)掃描多個主機(jī)。定義要掃描的網(wǎng)絡(luò)范圍為到。遍歷主機(jī)編號(0到9),生成每個主機(jī)的IP地址。對每個主機(jī),使用pool.apply_async()創(chuàng)建一個新進(jìn)程,調(diào)用scan_ports()函數(shù)掃描該主機(jī)的開放端口,并將結(jié)果存儲到results列表中。打印正在掃描的主機(jī)信息。調(diào)用pool.close()關(guān)閉進(jìn)程池,防止新的任務(wù)提交。調(diào)用pool.join()等待所有進(jìn)程完成。遍歷results列表,打印每個主機(jī)的開放端口及其對應(yīng)的服務(wù)名稱。(6)代碼運(yùn)行效果假設(shè)網(wǎng)絡(luò)中存在以下主機(jī)和開放端口::開放端口22(SSH)、80(HTTP):開放端口443(HTTPS)例11-6使用爬蟲程序獲取鏈接本例使用爬蟲程序獲取/網(wǎng)頁中的鏈接信息。importurllib.requestimportredefget_links(url):#模擬瀏覽器headers=("User-Agent","Mozilla/5.0(WindowsNT6.1;Win64;x64;rv:60.0)Gecko/20100101Firefox/60.0")opener=urllib.request.build_opener()opener.addheaders=[headers]#將opener安裝為全局urllib.request.install_opener(opener)file=urllib.request.urlopen(url)data=str(file.read())#根據(jù)需求構(gòu)建正則表達(dá)式pattern=r'https?://[^\s]+'links=pile(pattern).findall(data)#使用set函數(shù)去除重復(fù)元素unique_links=list(set(links))returnunique_links#指定需要爬取的網(wǎng)頁url='/'#獲取對應(yīng)網(wǎng)頁中包含的鏈接地址link_list=get_links(url)#遍歷列表結(jié)果并輸出forlinkinlink_list:print(link)以上程序運(yùn)行結(jié)果如圖11-6所示。圖11-6網(wǎng)站頁面的所有鏈接代碼解釋:(1)導(dǎo)入模塊importurllib.requestimportreurllib.request:用于發(fā)送網(wǎng)絡(luò)請求,獲取網(wǎng)頁內(nèi)容。re:用于處理正則表達(dá)式,用于從網(wǎng)頁內(nèi)容中提取鏈接。(2)定義函數(shù)get_links(url)defget_links(url):#模擬瀏覽器headers=("User-Agent","Mozilla/5.0(WindowsNT6.1;Win64;x64;rv:60.0)Gecko/20100101Firefox/60.0")opener=urllib.request.build_opener()opener.addheaders=[headers]#將opener安裝為全局urllib.request.install_opener(opener)file=urllib.request.urlopen(url)data=str(file.read())#根據(jù)需求構(gòu)建正則表達(dá)式pattern=r'https?://[^\s]+'links=pile(pattern).findall(data)#使用set函數(shù)去除重復(fù)元素unique_links=list(set(links))returnunique_links功能:該函數(shù)用于從指定的網(wǎng)頁中提取所有鏈接地址。邏輯:模擬瀏覽器行為:定義headers,模擬一個常見的瀏覽器(Firefox)的用戶代理(User-Agent)。①使用urllib.request.build_opener()創(chuàng)建一個請求處理器(opener),并設(shè)置請求頭為模擬的瀏覽器頭。②使用urllib.request.install_opener(opener)將該opener設(shè)置為全局的請求處理器,以便后續(xù)請求都使用該配置。獲取網(wǎng)頁內(nèi)容:①使用urllib.request.urlopen(url)發(fā)送請求,獲取網(wǎng)頁內(nèi)容。②將網(wǎng)頁內(nèi)容讀取為字符串(data=str(file.read()))。提取鏈接:①使用正則表達(dá)式pattern=r'https?://[^\s]+'匹配網(wǎng)頁中的所有鏈接。該正則表達(dá)式匹配以http://或https://開頭的鏈接,直到遇到空白字符為止。②使用pile(pattern).findall(data)找到所有匹配的鏈接。去重:使用set函數(shù)去除重復(fù)的鏈接,然后將其轉(zhuǎn)換為列表(unique_links=list(set(links)))。返回結(jié)果:返回去重后的鏈接列表。(3)指定需要爬取的網(wǎng)頁url='/'這里定義了一個變量url,但其值是一個帶標(biāo)簽的字符串,而不是一個純URL。正確的URL應(yīng)該是/。如果直接使用這個變量,可能會導(dǎo)致代碼無法正常運(yùn)行,因?yàn)閡rllib.request.urlopen()需要一個純URL字符串。(4)獲取對應(yīng)網(wǎng)頁中包含的鏈接地址link_list=get_links(url)調(diào)用get_links(url)函數(shù),傳入網(wǎng)頁地址,獲取該網(wǎng)頁中包含的所有鏈接地址。(5)遍歷列表結(jié)果并輸出forlinkinlink_list:print(link)遍歷返回的鏈接列表link_list,并逐行打印每個鏈接。(6)代碼運(yùn)行效果假設(shè)網(wǎng)頁/中包含以下鏈接:/about/contact運(yùn)行代碼后,輸出可能如下:/about/contact(7)注意事項(xiàng)URL格式問題:①在代碼中,url的值是一個帶標(biāo)簽的字符串,需要將其替換為純URL字符串(如/)。②可以通過字符串處理方法(如url=url.strip('<urlid="d1i7uunaf7n8hcqcfalg"type="url"status="parsed"title="清華大學(xué)出版社第五事業(yè)部()"wc="431">').strip('</url>'))來提取純URL。網(wǎng)絡(luò)請求限制:如果目標(biāo)網(wǎng)站有反爬蟲機(jī)制,可能會限制請求頻率或拒絕爬蟲訪問。建議合理設(shè)置請求間隔,避免對目標(biāo)網(wǎng)站造成過大壓力。正則表達(dá)式的局限性:當(dāng)前正則表達(dá)式r'https?://[^\s]+'可能無法匹配所有類型的鏈接(如帶有特殊字符的鏈接)。如果需要更全面地匹配鏈接,可以調(diào)整正則表達(dá)式。合法性:爬取網(wǎng)頁內(nèi)容需要遵守目標(biāo)網(wǎng)站的robots.txt文件規(guī)定,確保爬蟲行為合法合規(guī)。例11-7使用爬蟲程序獲取網(wǎng)頁文本本例使用爬蟲程序獲取“清華大學(xué)出版社”網(wǎng)頁上的文本內(nèi)容。importrequestsfrombs4importBeautifulSoup#目標(biāo)網(wǎng)頁URLurl="/intro.asp"try:#發(fā)送HTTP請求response=requests.get(url)response.raise_for_status()#檢查請求是否成功#設(shè)置正確的編碼response.encoding=response.apparent_encoding#使用requests庫的apparent_encoding屬性#解析網(wǎng)頁內(nèi)容soup=BeautifulSoup(response.text,'html.parser')#提取網(wǎng)頁中的文本內(nèi)容text_content=soup.get_text(strip=True,separator='\n')#使用strip和separator美化輸出print(text_content)exceptrequests.exceptions.RequestExceptionase:print(f"請求失敗:{e}")以上程序運(yùn)行結(jié)果如圖11-7所示(用戶在實(shí)際運(yùn)行上述程序時(shí),建議將代碼中的/intro.asp替換為希望爬取的網(wǎng)頁地址)。圖11-7爬取網(wǎng)頁文本代碼解釋:(1)導(dǎo)入模塊importrequestsfrombs4importBeautifulSouprequests:用于發(fā)送HTTP請求,獲取網(wǎng)頁內(nèi)容。BeautifulSoup:用于解析HTML或XML文檔,提取其中的數(shù)據(jù)。(2)目標(biāo)網(wǎng)頁URLurl="/intro.asp"這里定義了一個變量url,但其值是一個帶標(biāo)簽的字符串,而不是一個純URL。正確的URL應(yīng)該是/intro.asp。如果直接使用這個變量,可能會導(dǎo)致代碼無法正常運(yùn)行,因?yàn)閞equests.get(url)需要一個純URL字符串。(3)發(fā)送HTTP請求并處理異常try:#發(fā)送HTTP請求response=requests.get(url)response.raise_for_status()#檢查請求是否成功#設(shè)置正確的編碼response.encoding=response.apparent_encoding#使用requests庫的apparent_encoding屬性#解析網(wǎng)頁內(nèi)容soup=BeautifulSoup(response.text,'html.parser')#提取網(wǎng)頁中的文本內(nèi)容text_content=soup.get_text(strip=True,separator='\n')#使用strip和separator美化輸出print(text_content)exceptrequests.exceptions.RequestExceptionase:print(f"請求失?。簕e}")發(fā)送HTTP請求:①使用requests.get(url)發(fā)送GET請求到指定的URL。②response.raise_for_status()用于檢查請求是否成功。如果響應(yīng)狀態(tài)碼不是200(如404或500),會拋出異常。設(shè)置正確的編碼:response.encoding=response.apparent_encoding:設(shè)置響應(yīng)內(nèi)容的編碼為apparent_encoding,這是requests庫根據(jù)內(nèi)容猜測的編碼方式,通??梢哉_處理網(wǎng)頁內(nèi)容。解析網(wǎng)頁內(nèi)容:使用BeautifulSoup(response.text,'html.parser')解析響應(yīng)的HTML內(nèi)容。提取網(wǎng)頁中的文本內(nèi)容:使用soup.get_text(strip=True,separator='\n')提取網(wǎng)頁中的所有文本內(nèi)容,并去除多余的空白字符(strip=True),同時(shí)將文本內(nèi)容以換行符(\n)分隔,使輸出更加美觀。異常處理:使用try...except捕獲requests.exceptions.RequestException異常,如果請求失?。ㄈ缇W(wǎng)絡(luò)問題、URL錯誤、服務(wù)器返回錯誤狀態(tài)碼等),會打印錯誤信息。例11-8制作簡易聊天窗口本例制作簡易聊天窗口。本例演示如何通過Socket實(shí)現(xiàn)客戶端與服務(wù)器之間的簡單聊天功能??蛻舳丝梢韵蚍?wù)器發(fā)送文本消息,服務(wù)器接收后將消息內(nèi)容返回給客戶端。客戶端接收到響應(yīng)后顯示該信息,并可繼續(xù)發(fā)送消息。當(dāng)任一方輸入“byebye”時(shí),聊天會話結(jié)束。(1)創(chuàng)建server.py文件(服務(wù)器程序):importsockethost=socket.gethostname()#獲取主機(jī)地址port=12345#設(shè)置端口號s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建TCP/IP套接字s.bind((host,port))#綁定地址(host,port)到套接字s.listen(1)#設(shè)置最大連接數(shù)量sock,addr=s.accept()#被動接收TCP客戶端連接print('連接已經(jīng)建立')info=sock.recv(1024).decode()#接收客戶端數(shù)據(jù)whileinfo!='byebye':#判斷是否退出ifinfo:print('接收到的內(nèi)容:'+info)send_data=input('輸入發(fā)送內(nèi)容:')#輸入要發(fā)送的消息sock.send(send_data.encode())#發(fā)送TCP數(shù)據(jù)ifsend_data=='byebye':#如果發(fā)送了byebye,退出breakinfo=sock.recv(1024).decode()#接收客戶端數(shù)據(jù)sock.close()#關(guān)閉客戶端套接字s.close()#關(guān)閉服務(wù)器套接字(2)創(chuàng)建client.py文件(客戶端程序):importsocket#導(dǎo)入socket模塊s=socket.socket()#創(chuàng)建TCP/IP套接字host=socket.gethostname()#獲取主機(jī)地址port=12345#設(shè)置端口號s.connect((host,port))#主動初始化TCP服務(wù)器連接print("已連接")info=""whileinfo!='byebye':#判斷是否退出send_data=input('輸入發(fā)送內(nèi)容:')#輸入內(nèi)容s.send(send_data.encode())#發(fā)送TCP數(shù)據(jù)ifsend_data=='byebye':#判斷是否退出breakinfo=s.recv(1024).decode()#接收服務(wù)器數(shù)據(jù)print('接收到的內(nèi)容:'+info)s.close()#關(guān)閉套接字打開兩個cmd命令行窗口,分別運(yùn)行server.py和client.py文件,用戶可以在打開的兩個窗口中聊天,如圖11-8所示。(a)server.py(b)client.py圖11-8客戶端和服務(wù)器建立連接當(dāng)輸入byebye時(shí),將結(jié)束會話,如圖11-9所示。圖11-9結(jié)束會話代碼解釋:1)server.py文件(1)導(dǎo)入模塊importsoc
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 基于深度學(xué)習(xí)的幀間編碼優(yōu)化-洞察及研究
- 硫酸黏菌素對全球公共衛(wèi)生影響的長期觀察研究-洞察及研究
- 物流倉儲管理優(yōu)化措施與實(shí)施方案
- 安全員A證考試練習(xí)題(一)及答案詳解【新】
- 安全員A證考試過關(guān)檢測及答案詳解【易錯題】
- 安全員A證考試考試模擬試卷【必刷】附答案詳解
- 2025年安全員A證考試真題匯編及答案詳解【歷年真題】
- 公司運(yùn)營管理流程體系設(shè)計(jì)方案
- 安全員A證考試題庫檢測模擬題附完整答案詳解(典優(yōu))
- 信息安全管理制度及操作指南
- 干熱復(fù)合事件對北半球植被的影響及響應(yīng)機(jī)制研究
- 2025年四川單招護(hù)理試題及答案
- 鋼梁現(xiàn)場安裝施工質(zhì)量通病、原因分析及應(yīng)對措施
- 兒童肱骨髁上骨折術(shù)
- 腰椎常見病變課件
- 對賬單模板完整版本
- 工業(yè)互聯(lián)網(wǎng)安全技術(shù)(微課版)課件全套 項(xiàng)目1-7 工業(yè)互聯(lián)網(wǎng)及安全認(rèn)識-工業(yè)互聯(lián)網(wǎng)安全新技術(shù)認(rèn)識
- 甲狀腺乳腺外科診療規(guī)范
- 退換貨方案及措施
- 麻醉科常用耗材分類與管理要點(diǎn)
- 材料力學(xué)性能檢驗(yàn)工安全教育培訓(xùn)手冊
評論
0/150
提交評論