Python--day8--Socket编程/异常处理
介紹:
學(xué)習(xí)的第二階段,網(wǎng)絡(luò)編程。基于Python3 2016年12月29日 14:00:58
目錄:
Socket介紹
Socket簡(jiǎn)單交互實(shí)例
ssh模擬
Socket基本語(yǔ)法
SocketServer
異常處理
Socket,又稱作?套接字。用于描述IP地址和端口,是一個(gè)通信鏈的句柄,應(yīng)用程序通常通過(guò)“套接字”向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。
Socket 模塊 是針對(duì) ?服務(wù)器端?和?客戶端Socket ?進(jìn)行 ??打開(kāi) 讀寫(xiě) ?關(guān)閉
服務(wù)器:發(fā)送一條消息
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | import?socket#標(biāo)準(zhǔn)庫(kù) ip_port?=?('127.0.0.1',9998)?##聲明 sk?=?socket.socket()????##生成一個(gè)句柄 sk.bind(ip_port) sk.listen(5)????##監(jiān)聽(tīng) while?True: ????print('server?waiting...') ????conn,addr?=?sk.accept()???##會(huì)把客戶端的端口和IP,生成一個(gè)實(shí)例,只為這個(gè)客戶端服務(wù) ##??生成的實(shí)例,地址 ????client_data?=?conn.recv(1024)??##1024個(gè)字節(jié)/比特 ????print(str(client_data,'utf8')) ????conn.sendall(bytes('不要回答,不要回答,不要回答','utf8')) ????conn.close() |
客戶端:發(fā)送一條信息
| 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('請(qǐng)求占領(lǐng)地球','utf8')) server_reply?=?sk.recv(1024) print(str(server_reply,'utf8')) sk.close() |
服務(wù)器和客戶端交互消息
| 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#標(biāo)準(zhǔn)庫(kù) ip_port?=?('127.0.0.1',9998)?##聲明 sk?=?socket.socket()????##生成一個(gè)句柄 sk.bind(ip_port) sk.listen(5)????##監(jiān)聽(tīng) while?True: ????print('server?waiting...') ????conn,addr?=?sk.accept()??##會(huì)把客戶端的端口和IP,生成一個(gè)實(shí)例,只為這個(gè)客戶端服務(wù) ##??生成的實(shí)例,地址 ????client_data?=?conn.recv(1024)??##1024個(gè)字節(jié)/比特 ????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('請(qǐng)求占領(lǐng)地球','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() |
服務(wù)器和多個(gè)客戶端,第一個(gè)客戶端斷開(kāi)后,第二個(gè)進(jìn)行連接
| 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模擬執(zhí)行命令
| 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實(shí)例server.setsockopt(socket.SOL_SOCKET,?socket.SO_REUSEADDR,?1) server.bind(("localhost",9999))?#綁定ip?portserver.listen()??#開(kāi)始監(jiān)聽(tīng)while?True:?#第一層loop ????print("等待客戶端的連接...") ????conn,addr?=?server.accept()?#接受并建立與客戶端的連接,程序在此處開(kāi)始阻塞,只到有客戶端連接進(jìn)來(lái)... ????print("新連接:",addr?)????while?True: ????????data?=?conn.recv(1024)????????if?not?data:????????????print("客戶端斷開(kāi)了...")????????????break?#這里斷開(kāi)就會(huì)再次回到第一次外層的loop ????????print("收到命令:",data)????????#res?=?os.popen(data.decode()).read()?#py3?里socket發(fā)送的只有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"))?#發(fā)送數(shù)據(jù)之前,先告訴客戶端要發(fā)多少數(shù)據(jù)給它 ????????print("等待客戶ack應(yīng)答...") ????????client_final_ack?=?conn.recv(1024)?#等待客戶端響應(yīng) ????????print("客戶應(yīng)答:",client_final_ack.decode())????????print(type(res)) ????????conn.sendall(res)?#發(fā)送端也有最大數(shù)據(jù)量限制,所以這里用sendall,相當(dāng)于重復(fù)循環(huán)調(diào)用conn.send,直至數(shù)據(jù)發(fā)送完畢server.close() |
Socket基本語(yǔ)法
Socket ?Families 地址簇
socket.AF_UNIX ? ?unix本機(jī)進(jìn)程間通信
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) #獲取要連接的對(duì)端主機(jī)地址
sk.bind(address)
s.bind(address) 將套接字綁定到地址。address地址的格式取決于地址族。在AF_INET下,以元組(host,port)的形式表示地址。
sk.listen(backlog)
開(kāi)始監(jiān)聽(tīng)傳入連接。backlog指定在拒絕連接之前,可以掛起的最大連接數(shù)量。
sk.setblocking(bool)???
是否阻塞(默認(rèn)True),如果設(shè)置False,那么accept和recv時(shí)一旦無(wú)數(shù)據(jù),則報(bào)錯(cuò)。
sk.accept()
接受連接并返回(conn,address),其中conn是新的套接字對(duì)象,可以用來(lái)接收和發(fā)送數(shù)據(jù)。address是連接客戶端的地址。
接收TCP 客戶的連接(阻塞式)等待連接的到來(lái)
sk.connect(address)
連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯(cuò),返回socket.error錯(cuò)誤。
sk.connect_ex(address)
同上,只不過(guò)會(huì)有返回值,連接成功時(shí)返回 0 ,連接失敗時(shí)候返回編碼,例如:10061
sk.close()
關(guān)閉套接字
sk.recv(bufsize[,flag])
接受套接字的數(shù)據(jù)。數(shù)據(jù)以字符串形式返回,bufsize指定最多可以接收的8192 ?數(shù)量。flag提供有關(guān)消息的其他信息,通常可以忽略。
sk.recvfrom(bufsize[.flag])
與recv()類似,但返回值是(data,address)。其中data是包含接收數(shù)據(jù)的字符串,address是發(fā)送數(shù)據(jù)的套接字地址。
sk.send(string[,flag])
將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。即:可能未將指定內(nèi)容全部發(fā)送。
sk.sendall(string[,flag])
將string中的數(shù)據(jù)發(fā)送到連接的套接字,但在返回之前會(huì)嘗試發(fā)送所有數(shù)據(jù)。成功返回None,失敗則拋出異常。
? ? ? 內(nèi)部通過(guò)遞歸調(diào)用send,將所有內(nèi)容發(fā)送出去。
sk.sendto(string[,flag],address)
將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠(yuǎn)程地址。返回值是發(fā)送的字節(jié)數(shù)。該函數(shù)主要用于UDP協(xié)議。
sk.settimeout(timeout)
設(shè)置套接字操作的超時(shí)期,timeout是一個(gè)浮點(diǎn)數(shù),單位是秒。值為None表示沒(méi)有超時(shí)期。一般,超時(shí)期應(yīng)該在剛創(chuàng)建套接字時(shí)設(shè)置,因?yàn)樗鼈兛赡苡糜谶B接的操作(如 client 連接最多等待5s )
sk.getpeername()
返回連接套接字的遠(yuǎn)程地址。返回值通常是元組(ipaddr,port)。
sk.getsockname()
返回套接字自己的地址。通常是一個(gè)元組(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)??判斷一個(gè)對(duì)象是否是類cls的對(duì)象
-
issubclass(sub,super) ?檢查sub類是否是super類的派生類(子類)
異常基礎(chǔ)
| 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:??##??萬(wàn)能??所有的異常 ????????print('出現(xiàn)異常,信息如下:') ????????print(e) ????pass |
常見(jiàn)錯(cuò)誤
AttributeError ? ? ? 試圖訪問(wèn)一個(gè)對(duì)象沒(méi)有的樹(shù)形,比如foo.x,但是foo沒(méi)有屬性x
IOError ? ? ? ? ? ? ? ? 輸入/輸出異常;基本上是無(wú)法打開(kāi)文件
ImportError ? ? ? ? ?無(wú)法引入模塊或包;基本上是路徑問(wèn)題或名稱錯(cuò)誤
IndentationError ? 語(yǔ)法錯(cuò)誤(的子類)?;代碼沒(méi)有正確對(duì)齊
IndexError ? ? ? ? ? ?下標(biāo)索引超出序列邊界,比如當(dāng)x只有三個(gè)元素,卻試圖訪問(wèn)x[5]
KeyError ? ? ? ? ? ? ? ?試圖訪問(wèn)字典里不存在的鍵
KeyboardInterrupt?Ctrl+C被按下
NameError ? ? ? ? ? ? 使用一個(gè)還未被賦予對(duì)象的變量
SyntaxError ? ? ? ? ? ?Python代碼非法,代碼不能編譯(個(gè)人認(rèn)為這是語(yǔ)法錯(cuò)誤,寫(xiě)錯(cuò)了)
TypeError ? ? ? ? ? ?????傳入對(duì)象類型與要求的不符合
UnboundLocalError ?試圖訪問(wèn)一個(gè)還未被設(shè)置的局部變量,基本上是由于另有一個(gè)同名的全局變量,
導(dǎo)致你以為正在訪問(wèn)它
ValueError ? ? ? ? ? ? ? ?傳入一個(gè)調(diào)用者不期望的值,即使值的類型是正確的
自定義異常
| 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) |
異常其他結(jié)構(gòu)
try:
????# 主代碼塊
????pass
except?KeyError as e:
????# 異常時(shí),執(zhí)行該塊
????pass
else:
????# 主代碼塊執(zhí)行完,執(zhí)行該塊
????pass
finally:
????# 無(wú)論異常與否,最終執(zhí)行該塊
????pass
assert ?條件 ? 斷言
assert 1 == 1? ? ?
本文轉(zhuǎn)自 295631788 51CTO博客,原文鏈接:,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者
總結(jié)
以上是生活随笔為你收集整理的Python--day8--Socket编程/异常处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Squid 反向代理服务器配置
- 下一篇: CrazyWing:Python自动化运