Python--day8--Socket编程/异常处理
介紹:
學習的第二階段,網絡編程。基于Python3 2016年12月29日 14:00:58
目錄:
Socket介紹
Socket簡單交互實例
ssh模擬
Socket基本語法
SocketServer
異常處理
Socket,又稱作?套接字。用于描述IP地址和端口,是一個通信鏈的句柄,應用程序通常通過“套接字”向網絡發出請求或者應答網絡請求。
Socket 模塊 是針對 ?服務器端?和?客戶端Socket ?進行 ??打開 讀寫 ?關閉
服務器:發送一條消息
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | import?socket#標準庫 ip_port?=?('127.0.0.1',9998)?##聲明 sk?=?socket.socket()????##生成一個句柄 sk.bind(ip_port) sk.listen(5)????##監聽 while?True: ????print('server?waiting...') ????conn,addr?=?sk.accept()???##會把客戶端的端口和IP,生成一個實例,只為這個客戶端服務 ##??生成的實例,地址 ????client_data?=?conn.recv(1024)??##1024個字節/比特 ????print(str(client_data,'utf8')) ????conn.sendall(bytes('不要回答,不要回答,不要回答','utf8')) ????conn.close() |
客戶端:發送一條信息
| 1 2 3 4 5 6 7 8 | import?socket ip_port?=?('127.0.0.1',9998) sk?=?socket.socket() sk.connect(ip_port) sk.sendall(bytes('請求占領地球','utf8')) server_reply?=?sk.recv(1024) print(str(server_reply,'utf8')) sk.close() |
服務器和客戶端交互消息
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import?socket#標準庫 ip_port?=?('127.0.0.1',9998)?##聲明 sk?=?socket.socket()????##生成一個句柄 sk.bind(ip_port) sk.listen(5)????##監聽 while?True: ????print('server?waiting...') ????conn,addr?=?sk.accept()??##會把客戶端的端口和IP,生成一個實例,只為這個客戶端服務 ##??生成的實例,地址 ????client_data?=?conn.recv(1024)??##1024個字節/比特 ????print(str(client_data,'utf8')) ????conn.sendall(bytes('不要回答,不要回答,不要回答','utf8')) ????while?True: ????????client_data?=?conn.recv(1024) ????????print(str(client_data,'utf8')) ????????server_response?=?input("\033[31;1m>>:\033[0m").strip() ????????conn.send(bytes(server_response,'utf8')) ????conn.close() import?socket ip_port?=?('127.0.0.1',9998) sk?=?socket.socket() sk.connect(ip_port) sk.sendall(bytes('請求占領地球','utf8')) server_reply?=?sk.recv(1024) print(str(server_reply,'utf8')) while??True: ????user_input?=input(">>:").strip() ????sk.sendall(bytes(user_input,'utf8')) ????server_reply?=?sk.recv(1024) ????print(str(server_reply,?'utf8')) sk.close() |
服務器和多個客戶端,第一個客戶端斷開后,第二個進行連接
| 1 2 3 4 5 6 7 8 9 | conn.sendall(bytes('不要回答,不要回答,不要回答','utf8')) while?True: ????try: ????????client_data?=?conn.recv(1024) ????????print("recv:",str(client_data,'utf8')) ????except??Exception:??####??前面是windows的?,后面是linux??:if?not??client_data:break? ????????print("client??closed?,break") ????????break ????conn.send(client_data) |
ssh模擬執行命令
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import?socketimport?os,subprocess server?=?socket.socket()?#獲得socket實例server.setsockopt(socket.SOL_SOCKET,?socket.SO_REUSEADDR,?1) server.bind(("localhost",9999))?#綁定ip?portserver.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!".encode("utf-8") ????????conn.send(str(len(res)).encode("utf-8"))?#發送數據之前,先告訴客戶端要發多少數據給它 ????????print("等待客戶ack應答...") ????????client_final_ack?=?conn.recv(1024)?#等待客戶端響應 ????????print("客戶應答:",client_final_ack.decode())????????print(type(res)) ????????conn.sendall(res)?#發送端也有最大數據量限制,所以這里用sendall,相當于重復循環調用conn.send,直至數據發送完畢server.close() |
Socket基本語法
Socket ?Families 地址簇
socket.AF_UNIX ? ?unix本機進程間通信
socket.AF_INET?? ipv4
socket.AF_INET6 ?ipv6
Scoket ?Types
socket.SOCK_STREAM?? ?TCP
socket.SOCK_DGRAM ? ? UDP
socket.SOCK_RAW ? ? ? ?原始套接字
socket.SOCK_RDM ? ? ?可靠的UDP
socket.socket(family=AF_INET,?type=SOCK_STREAM,?proto=0,?fileno=None)
socket.socketpair([family[,?type[,?proto]]]) ?
socket.create_connection(address[,?timeout[,?source_address]])
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指定在拒絕連接之前,可以掛起的最大連接數量。
sk.setblocking(bool)???
是否阻塞(默認True),如果設置False,那么accept和recv時一旦無數據,則報錯。
sk.accept()
接受連接并返回(conn,address),其中conn是新的套接字對象,可以用來接收和發送數據。address是連接客戶端的地址。
接收TCP 客戶的連接(阻塞式)等待連接的到來
sk.connect(address)
連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
sk.connect_ex(address)
同上,只不過會有返回值,連接成功時返回 0 ,連接失敗時候返回編碼,例如:10061
sk.close()
關閉套接字
sk.recv(bufsize[,flag])
接受套接字的數據。數據以字符串形式返回,bufsize指定最多可以接收的8192 ?數量。flag提供有關消息的其他信息,通常可以忽略。
sk.recvfrom(bufsize[.flag])
與recv()類似,但返回值是(data,address)。其中data是包含接收數據的字符串,address是發送數據的套接字地址。
sk.send(string[,flag])
將string中的數據發送到連接的套接字。返回值是要發送的字節數量,該數量可能小于string的字節大小。即:可能未將指定內容全部發送。
sk.sendall(string[,flag])
將string中的數據發送到連接的套接字,但在返回之前會嘗試發送所有數據。成功返回None,失敗則拋出異常。
? ? ? 內部通過遞歸調用send,將所有內容發送出去。
sk.sendto(string[,flag],address)
將數據發送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址。返回值是發送的字節數。該函數主要用于UDP協議。
sk.settimeout(timeout)
設置套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。一般,超時期應該在剛創建套接字時設置,因為它們可能用于連接的操作(如 client 連接最多等待5s )
sk.getpeername()
返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。
sk.getsockname()
返回套接字自己的地址。通常是一個元組(ipaddr,port)
sk.fileno()
套接字的文件描述符
SockerServer ? ? ? ? 多線程
+------------+|?BaseServer?|+------------+??????|??????v+-----------+????????+------------------+|?TCPServer?|------->|?UnixStreamServer?|+-----------+????????+------------------+??????|??????v+-----------+????????+--------------------+|?UDPServer?|------->|?UnixDatagramServer?|+-----------+????????+--------------------+-
class?socketserver.ForkingTCPServer
-
class?socketserver.ForkingUDPServer
-
class?socketserver.ThreadingTCPServer
-
class?socketserver.ThreadingUDPServer
例子
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import?socketserver class?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.ThreadingTCPServer((HOST,?PORT),?MyTCPHandler) ????#?Activate?the?server;?this?will?keep?running?until?you ????#?interrupt?the?program?with?Ctrl-C ????server.serve_forever() |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import?socket import?sys HOST,?PORT?=?"localhost",?9999 data?=?"?".join(sys.argv[1:]) #?Create?a?socket?(SOCK_STREAM?means?a?TCP?socket) sock?=?socket.socket(socket.AF_INET,?socket.SOCK_STREAM) try: ????#?Connect?to?server?and?send?data ????sock.connect((HOST,?PORT)) ????sock.sendall(bytes(data?+?"\n",?"utf-8")) ????#?Receive?data?from?the?server?and?shut?down ????received?=?str(sock.recv(1024),?"utf-8") finally: ????sock.close() print("Sent:?????{}".format(data)) print("Received:?{}".format(received)) |
異常處理
-
isinstacne(obj,cls)??判斷一個對象是否是類cls的對象
-
issubclass(sub,super) ?檢查sub類是否是super類的派生類(子類)
異常基礎
| 1 2 3 4 5 6 7 8 9 10 11 | ?while?True: ????num1?=?input('num1:') ????num2?=?input('num2:') ????try: ????????num1?=?int(num1) ????????num2?=?int(num2) ????????result?=?num1?+?num2 ????except?Exception?as?e:??##??萬能??所有的異常 ????????print('出現異常,信息如下:') ????????print(e) ????pass |
常見錯誤
AttributeError ? ? ? 試圖訪問一個對象沒有的樹形,比如foo.x,但是foo沒有屬性x
IOError ? ? ? ? ? ? ? ? 輸入/輸出異常;基本上是無法打開文件
ImportError ? ? ? ? ?無法引入模塊或包;基本上是路徑問題或名稱錯誤
IndentationError ? 語法錯誤(的子類)?;代碼沒有正確對齊
IndexError ? ? ? ? ? ?下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5]
KeyError ? ? ? ? ? ? ? ?試圖訪問字典里不存在的鍵
KeyboardInterrupt?Ctrl+C被按下
NameError ? ? ? ? ? ? 使用一個還未被賦予對象的變量
SyntaxError ? ? ? ? ? ?Python代碼非法,代碼不能編譯(個人認為這是語法錯誤,寫錯了)
TypeError ? ? ? ? ? ?????傳入對象類型與要求的不符合
UnboundLocalError ?試圖訪問一個還未被設置的局部變量,基本上是由于另有一個同名的全局變量,
導致你以為正在訪問它
ValueError ? ? ? ? ? ? ? ?傳入一個調用者不期望的值,即使值的類型是正確的
自定義異常
| 1 2 3 4 5 6 7 8 9 | class?WupeiqiException(Exception): ????def?__init__(self,?msg): ????????self.message?=?msg ????def?__str__(self): ????????return?self.message try: ????raise?WupeiqiException('我的異常') except?WupeiqiException?as?e: ????print(e) |
異常其他結構
try:
????# 主代碼塊
????pass
except?KeyError as e:
????# 異常時,執行該塊
????pass
else:
????# 主代碼塊執行完,執行該塊
????pass
finally:
????# 無論異常與否,最終執行該塊
????pass
assert ?條件 ? 斷言
assert 1 == 1? ? ?
本文轉自 295631788 51CTO博客,原文鏈接:,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的Python--day8--Socket编程/异常处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Squid 反向代理服务器配置
- 下一篇: Postfix+dovecot+extm