python爬蟲教程,python基礎7--socket

 2023-11-19 阅读 29 评论 0

摘要:1. Socket介紹 實現一個socket至少要分以下幾步,(偽代碼) Socket socket = getSocket(type = "TCP")? #設定好協議類型 connect(socket, address = "1.2.3.4", port = "80") #連接遠程機器 send(socket, "Hello, world!&#

1. Socket介紹

實現一個socket至少要分以下幾步,(偽代碼)

Socket socket = getSocket(type = "TCP")? #設定好協議類型
connect(socket, address = "1.2.3.4", port = "80") #連接遠程機器
send(socket, "Hello, world!") #發送消息
close(socket) #關閉連接

Socket Families(地址簇)

socket.AF_UNIX unix本機進程間通信?

socket.AF_INET IPV4 

socket.AF_INET6 ?IPV6

?

Socket Types

python爬蟲教程。socket.SOCK_STREAM ?#for tcp

socket.SOCK_DGRAM ? #for udp

socket.SOCK_RAW ? ? #原始套接字,普通的套接字無法處理ICMP、IGMP等網絡報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由用戶構造IP頭。

socket.SOCK_RDM ?#是一種可靠的UDP形式,即保證交付數據報但不保證順序。SOCK_RAM用來提供對原始協議的低級訪問,在需要執行某些特殊操作時使用,如發送ICMP報文。SOCK_RAM通常僅限于高級用戶或管理員運行的程序使用。

socket.SOCK_SEQPACKET #廢棄了

?

2. Socket 參數介紹

socket.socket(family=AF_INET,?type=SOCK_STREAM,?proto=0,?fileno=None) ?必會

python基礎教程。socket.getaddrinfo(host,?port,?family=0,?type=0,?proto=0,?flags=0) #獲取要連接的對端主機地址 必會

sk.bind(address) 必會

  s.bind(address) 將套接字綁定到地址。address地址的格式取決于地址族。在AF_INET下,以元組(host,port)的形式表示地址。

sk.listen(backlog) 必會

  開始監聽傳入連接。backlog指定在拒絕連接之前,可以掛起的最大連接數量。

? ? ? backlog等于5,表示內核已經接到了連接請求,但服務器還沒有調用accept進行處理的連接個數最大為5
? ? ? 這個值不能無限大,因為要在內核中維護連接隊列

python socket。sk.setblocking(bool) 必會

  是否阻塞(默認True),如果設置False,那么accept和recv時一旦無數據,則報錯。

sk.accept() 必會

  接受連接并返回(conn,address),其中conn是新的套接字對象,可以用來接收和發送數據。address是連接客戶端的地址。

  接收TCP 客戶的連接(阻塞式)等待連接的到來

sk.connect(address) 必會

python語言程序設計?  連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。

sk.connect_ex(address)

  同上,只不過會有返回值,連接成功時返回 0 ,連接失敗時候返回編碼,例如:10061

sk.close() 必會

  關閉套接字

sk.recv(bufsize[,flag]) 必會

python有什么用?  接受套接字的數據。數據以字符串形式返回,bufsize指定最多可以接收的數量。flag提供有關消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag])

  與recv()類似,但返回值是(data,address)。其中data是包含接收數據的字符串,address是發送數據的套接字地址。

sk.send(string[,flag]) 必會

  將string中的數據發送到連接的套接字。返回值是要發送的字節數量,該數量可能小于string的字節大小。即:可能未將指定內容全部發送。

sk.sendall(string[,flag]) 必會

python3、  將string中的數據發送到連接的套接字,但在返回之前會嘗試發送所有數據。成功返回None,失敗則拋出異常。

? ? ? 內部通過遞歸調用send,將所有內容發送出去。

sk.sendto(string[,flag],address)

  將數據發送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址。返回值是發送的字節數。該函數主要用于UDP協議。

sk.settimeout(timeout) 必會

  設置套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。一般,超時期應該在剛創建套接字時設置,因為它們可能用于連接的操作(如 client 連接最多等待5s )

websocket python。sk.getpeername() ?必會

  返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。

sk.getsockname()?

  返回套接字自己的地址。通常是一個元組(ipaddr,port)

sk.fileno()?

  套接字的文件描述符

c++ socket編程,socket.sendfile(file,?offset=0,?count=None)

? ? ?發送文件 ,但目前多數情況下并無什么卵用。

?

3. 基本Socket實例

服務端:

客戶端:

python asyncio、

?

實現多次的數據交互示例:服務端

客戶端

python socket客戶端。服務端優化

?

4.Socket實現多連接處理

conn,addr = server.accept() #接受并建立與客戶端的連接,程序在此處開始阻塞,只到有客戶端連接進來...
我們知道上面這句話負責等待并接收新連接,對于上面那個程序,其實在while break之后,只要讓程序再次回到上面這句代碼這,就可以讓服務端繼續接下一個客戶啦。

?

5.通過socket實現簡單的ssh

服務端:

python編程100例。客戶端:

在開始解決上面問題3之前,我們要考慮,客戶端要循環接收服務器端的大量數據返回直到一條命令的結果全部返回為止, 但問題是客戶端知道服務器端返回的數據有多大么?答案是不知道,那既然不知道服務器的要返回多大的數據,那客戶端怎么知道要循環接收多少次呢?答案是不知道,擦,那咋辦? 總不能靠猜吧?呵呵。。。 當然不能,那只能讓服務器在發送數據之前主動告訴客戶端,要發送多少數據給客戶端,然后再開始發送數據,yes, 機智如我,搞起。

先簡單測試接收數據量大小,服務端優化

import socket
import os,subprocessserver = socket.socket() #獲得socket實例 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(("localhost",9998)) #綁定ip port server.listen() #開始監聽 while True: #第一層loop print("等待客戶端的連接...") conn,addr = server.accept() #接受并建立與客戶端的連接,程序在此處開始阻塞,只到有客戶端連接進來... print("新連接:",addr ) while True: data = conn.recv(1024) if not data: print("客戶端斷開了...") break #這里斷開就會再次回到第一次外層的loop print("收到命令:",data) #res = os.popen(data.decode()).read() #py3 里socket發送的只有bytes,os.popen又只能接受str,所以要decode一下 res = subprocess.Popen(data,shell=True,stdout=subprocess.PIPE).stdout.read() #跟上面那條命令的效果是一樣的 if len(res) == 0: res = "cmd exec success,has not output!" conn.send(str(len(res)).endcode("utf-8")) #發送數據之前,先告訴客戶端要發多少數據給它 conn.sendall(res.encode("utf-8")) #發送端也有最大數據量限制,所以這里用sendall,相當于重復循環調用conn.send,直至數據發送完畢  server.close()

6. SocketServer

socketserver一共有這么幾種類型:

class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass,bind_and_activate=True)
基本的socketserver代碼:
import socketserverclass MyTCPHandler(socketserver.BaseRequestHandler):""" The request handler class for our server. It is instantiated once per connection to the server, and must override the handle() method to implement communication to the client. """ def handle(self): # self.request is the TCP socket connected to the client self.data = self.request.recv(1024).strip() print("{} wrote:".format(self.client_address[0])) print(self.data) # just send back the same data, but upper-cased  self.request.sendall(self.data.upper()) if __name__ == "__main__": HOST, PORT = "localhost", 9999 # Create the server, binding to localhost on port 9999 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) # Activate the server; this will keep running until you # interrupt the program with Ctrl-C server.serve_forever()


讓你的socketserver并發起來, 必須選擇使用以下一個多并發的類

python需要學哪些,class?socketserver.ForkingTCPServer

class?socketserver.ForkingUDPServer

class?socketserver.ThreadingTCPServer

class?socketserver.ThreadingUDPServer

so 只需要把下面這句

server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
換成下面這個,就可以多并發了,這樣,客戶端每連進一個來,服務器端就會分配一個新的線程來處理這個客戶端的請求
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)

轉載于:https://www.cnblogs.com/chengyazhou/p/6834262.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/181717.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息