Python Socket 的更多方法介紹
一.SOCKET的更多方法介紹
更多方法:
服務端套接字函數 s.bind()????綁定(主機,端口號)到套接字 s.listen()??開始TCP監聽 s.accept()??被動接受TCP客戶的連接,(阻塞式)等待連接的到來 客戶端套接字函數 s.connect()?????主動初始化TCP服務器連接 s.connect_ex()??connect()函數的擴展版本,出錯時返回出錯碼,而不是拋出異常 公共用途的套接字函數 s.recv()????????????接收TCP數據 s.send()????????????發送TCP數據 s.sendall()?????????發送TCP數據 s.recvfrom()????????接收UDP數據 s.sendto()??????????發送UDP數據 s.getpeername()?????連接到當前套接字的遠端的地址 s.getsockname()?????當前套接字的地址 s.getsockopt()??????返回指定套接字的參數 s.setsockopt()??????設置指定套接字的參數 s.close()???????????關閉套接字 面向鎖的套接字方法 s.setblocking()?????設置套接字的阻塞與非阻塞模式 s.settimeout()??????設置阻塞套接字操作的超時時間 s.gettimeout()??????得到阻塞套接字操作的超時時間 面向文件的套接字的函數 s.fileno()??????????套接字的文件描述符 s.makefile()????????創建一個與該套接字相關的文件
send 和 sendall 方法:
官方文檔對SOCKET模塊下的socket.send()和socket.sendall()解釋如下: socket.send(string[,?flags]) Send?data?to?the?socket.?The?socket?must?be?connected?to?a?remote?socket.?The?optional?flags?argument?has?the?same?meaning?as?for?recv()?above.? Returns?the?number?of?bytes?sent.?Applications?are?responsible?for?checking?that?all?data?has?been?sent;? if?only?some?of?the?data?was?transmitted,?the?application?needs?to?attempt?delivery?of?the?remaining?data. send()的返回值是發送的字節數量,這個數量值可能小于要發送的string的字節數,也就是說可能無法發送string中所有的數據。如果有錯誤則會拋出異常。 socket.sendall(string[,?flags]) Send?data?to?the?socket.?The?socket?must?be?connected?to?a?remote?socket.?The?optional?flags?argument?has?the?same?meaning?as?for?recv()?above.? Unlike?send(),?this?method?continues?to?send?data?from?string?until?either?all?data?has?been?sent?or?an?error?occurs.? None?is?returned?on?success.?On?error,?an?exception?is?raised,?and?there?is?no?way?to?determine?how?much?data,?if?any,?was?successfully?sent. 嘗試發送string的所有數據,成功則返回None,失敗則拋出異常。 故,下面兩段代碼是等價的: #sock.sendall('Hello?world\n') #buffer?=?'Hello?world\n' #while?buffer: #????bytes?=?sock.send(buffer) #????buffer?=?buffer[bytes:]
二.驗證客戶端鏈接的合法性
如果你想在分布式系統中實現一個簡單的客戶端鏈接認證功能,又不像SSL那么復雜,那么利用hmac+加鹽的方式來實現
服務端:
#_*_coding:utf-8_*_ from?socket?import?* import?hmac,os secret_key=b'linhaifeng?bang?bang?bang' def?conn_auth(conn): ????''' ????認證客戶端鏈接 ????:param?conn: ????:return: ????''' ????print('開始驗證新鏈接的合法性') ????msg=os.urandom(32) ????conn.sendall(msg) ????h=hmac.new(secret_key,msg) ????digest=h.digest() ????respone=conn.recv(len(digest)) ????return?hmac.compare_digest(respone,digest) def?data_handler(conn,bufsize=1024): ????if?not?conn_auth(conn): ????????print('該鏈接不合法,關閉') ????????conn.close() ????????return ????print('鏈接合法,開始通信') ????while?True: ????????data=conn.recv(bufsize) ????????if?not?data:break ????????conn.sendall(data.upper()) def?server_handler(ip_port,bufsize,backlog=5): ????''' ????只處理鏈接 ????:param?ip_port: ????:return: ????''' ????tcp_socket_server=socket(AF_INET,SOCK_STREAM) ????tcp_socket_server.bind(ip_port) ????tcp_socket_server.listen(backlog) ????while?True: ????????conn,addr=tcp_socket_server.accept() ????????print('新連接[%s:%s]'?%(addr[0],addr[1])) ????????data_handler(conn,bufsize) if?__name__?==?'__main__': ????ip_port=('127.0.0.1',9999) ????bufsize=1024 ????server_handler(ip_port,bufsize)
客戶端(合法性):
#_*_coding:utf-8_*_ __author__?=?'Linhaifeng' from?socket?import?* import?hmac,os secret_key=b'linhaifeng?bang?bang?bang' def?conn_auth(conn): ????''' ????驗證客戶端到服務器的鏈接 ????:param?conn: ????:return: ????''' ????msg=conn.recv(32) ????h=hmac.new(secret_key,msg) ????digest=h.digest() ????conn.sendall(digest) def?client_handler(ip_port,bufsize=1024): ????tcp_socket_client=socket(AF_INET,SOCK_STREAM) ????tcp_socket_client.connect(ip_port) ????conn_auth(tcp_socket_client) ????while?True: ????????data=input('>>:?').strip() ????????if?not?data:continue ????????if?data?==?'quit':break ????????tcp_socket_client.sendall(data.encode('utf-8')) ????????respone=tcp_socket_client.recv(bufsize) ????????print(respone.decode('utf-8')) ????tcp_socket_client.close() if?__name__?==?'__main__': ????ip_port=('127.0.0.1',9999) ????bufsize=1024 ????client_handler(ip_port,bufsize)
客戶端(非法:不知道加密方式)
#_*_coding:utf-8_*_ __author__?=?'Linhaifeng' from?socket?import?* def?client_handler(ip_port,bufsize=1024): ????tcp_socket_client=socket(AF_INET,SOCK_STREAM) ????tcp_socket_client.connect(ip_port) ????while?True: ????????data=input('>>:?').strip() ????????if?not?data:continue ????????if?data?==?'quit':break ????????tcp_socket_client.sendall(data.encode('utf-8')) ????????respone=tcp_socket_client.recv(bufsize) ????????print(respone.decode('utf-8')) ????tcp_socket_client.close() if?__name__?==?'__main__': ????ip_port=('127.0.0.1',9999) ????bufsize=1024 ????client_handler(ip_port,bufsize)
客戶端(非法:不知道secret_key)
#_*_coding:utf-8_*_ __author__?=?'Linhaifeng' from?socket?import?* import?hmac,os secret_key=b'linhaifeng?bang?bang?bang1111' def?conn_auth(conn): ????''' ????驗證客戶端到服務器的鏈接 ????:param?conn: ????:return: ????''' ????msg=conn.recv(32) ????h=hmac.new(secret_key,msg) ????digest=h.digest() ????conn.sendall(digest) def?client_handler(ip_port,bufsize=1024): ????tcp_socket_client=socket(AF_INET,SOCK_STREAM) ????tcp_socket_client.connect(ip_port) ????conn_auth(tcp_socket_client) ????while?True: ????????data=input('>>:?').strip() ????????if?not?data:continue ????????if?data?==?'quit':break ????????tcp_socket_client.sendall(data.encode('utf-8')) ????????respone=tcp_socket_client.recv(bufsize) ????????print(respone.decode('utf-8')) ????tcp_socket_client.close() if?__name__?==?'__main__': ????ip_port=('127.0.0.1',9999) ????bufsize=1024 ????client_handler(ip_port,bufsize)
三.socketserver
socketserver 源碼的學習解讀:
server端:
import?socketserver class?Myserver(socketserver.BaseRequestHandler): ????def?handle(self): ????????self.data?=?self.request.recv(1024).strip() ????????print("{}?wrote:".format(self.client_address[0])) ????????print(self.data) ????????self.request.sendall(self.data.upper()) if?__name__?==?"__main__": ????HOST,?PORT?=?"127.0.0.1",?9999 ????#?設置allow_reuse_address允許服務器重用地址 ????socketserver.TCPServer.allow_reuse_address?=?True ????#?創建一個server,?將服務地址綁定到127.0.0.1:9999 ????server?=?socketserver.TCPServer((HOST,?PORT),Myserver) ????#?讓server永遠運行下去,除非強制停止程序 ????server.serve_forever()
client 端:
import?socket HOST,?PORT?=?"127.0.0.1",?9999 data?=?"hello" #?創建一個socket鏈接,SOCK_STREAM代表使用TCP協議 with?socket.socket(socket.AF_INET,?socket.SOCK_STREAM)?as?sock: ????sock.connect((HOST,?PORT))??????????#?鏈接到客戶端 ????sock.sendall(bytes(data?+?"\n",?"utf-8"))?#?向服務端發送數據 ????received?=?str(sock.recv(1024),?"utf-8")#?從服務端接收數據 print("Sent:?????{}".format(data)) print("Received:?{}".format(received))
軟件開發 人工智能 云計算 機器學習
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。