25 python 初學(socket,socketserver)
參考blog :www.cnblogs.com/yuanchenqi/articles/5692716.html
1. sk = socket.socket()
裏面有兩個重要的參數,family 和 type
type:
SOCK_STREAM : tcp 默認
SOCK_DGRAM :udp
family:
family = AF_INET : 服務器之間的通信(默認)
family = AF_INET6 : 服務器之間的通信
family=AF_UNIX:unix不同進程間通信
server 下的方法:
bind() 、 listen() 、 accept()
recv() 、 send() 、
close()
client 下的方法:
connect()
recv() 、send( string ) 、sendall() # 傳送的類型一定是 byte 類型
close()
# _author: lily # _date: 2019/1/25 # server 端 import socket sk = socket.socket() address = (‘127.0.0.1‘, 8000) sk.bind(address) sk.listen(3) print(‘waiting‘) # print(sk) conn, address_client = sk.accept()while 1: send_data = input(‘input>>‘) if send_data == ‘exit‘: break conn.send(bytes(send_data, ‘utf8‘)) rec_data = conn.recv(1024) print(str(rec_data, ‘utf8‘)) conn.close()
# _author: lily # _date: 2019/1/25 # client 端 import socket sk = socket.socket() # print(sk)adress = (‘127.0.0.1‘, 8000) sk.connect(adress) while 1: rec_data = sk.recv(1024) # 會阻塞,直到收到數據 if not rec_data: break print(str(rec_data, ‘utf8‘)) send_data = input(‘>>‘) sk.send(bytes(send_data, ‘utf8‘)) sk.close()
socket 流程:
1. 先開啟服務端,bind 綁定ip 和端口;
2. 其次 listen 監聽,裏面的數字表示有多少客戶端可排隊(不包括當前正在通信的,排隊表示可連接但是不能通信。比如設定上限為3,當第四個客戶端來連接時就會報錯無法連接)
3. 接著需要 accept(),阻塞等待連接。accept 接受到的值是對方的 sk,進行連接(相當於兩端建立了一個通道,server 和 client 都使用的這個通道,只是各自的命名不同)。
4. 保證一收一發原則
5. 關閉時關閉這個通道。 conn.close()
1. 客戶端進行連接,先創建一個socket 對象 sk
2. sk 使用 connect 連接服務端
3. 保證一收一發原則
4. 關閉時 sk.close()
粘包現象的解決辦法:
加一個 conn.recv(1024) 進行阻塞,將兩個連續的conn.send()分隔開
編碼拾遺:
- str:unicode
- bytes:十六進制
- 由 str -> bytes:編碼
s = ‘hello 你好’
b = bytes(s, ‘utf8’)
b2 = s.encode(‘utf8’) # 兩個是一樣的
- 由 bytes -> str:解碼
s2 = str(b2, ‘utf8’)
s2 = b2.decode(‘utf8’)
socketserver:
1. 調用模塊
2. 自己寫一個類,繼承 socketserver.BaseRequestHandler,並重寫 handle()方法
3. main 方法內:
調用 socketserver.ThreadingTCPServer,創建一個實例
# _author: lily # _date: 2019/1/28 # Server 端 import socketserver class myserver(socketserver.BaseRequestHandler): # 主要邏輯 def handle(self): print(‘server starting...‘) while True: conn = self.request print(self.client_address) while True: client_data = conn.recv(1024) print(str(client_data, ‘utf8‘)) print(‘waiting‘) send_data = input(‘input>>‘) conn.sendall(bytes(send_data, ‘utf8‘)) # conn.sendall(client_data) conn.close() if __name__ == ‘__main__‘: server = socketserver.ThreadingTCPServer((‘127.0.0.1‘, 8091), myserver) server.serve_forever()
# _author: lily # _date: 2019/1/28 # client 端 import socket address = (‘127.0.0.1‘, 8091) sk = socket.socket() sk.connect(address) print(‘client starting...‘) while True: data = input(‘input>>‘) sk.sendall(bytes(data, ‘utf8‘)) recv_data = sk.recv(1024) print(str(recv_data, ‘utf8‘)) sk.close()
實例:
cmd 命令:
server 端:
# _author: lily # _date: 2019/1/26 import socket import subprocess sk = socket.socket() address = (‘127.0.0.1‘, 8000) sk.bind(address) sk.listen(3) print(‘waiting‘) # print(sk) conn, address_client = sk.accept() while 1: try: rec_data = conn.recv(1024) except Exception: break if not rec_data: break print(‘--client message--‘, str(rec_data, ‘utf8‘)) a = subprocess.Popen(str(rec_data, ‘utf8‘), shell=True, stdout=subprocess.PIPE) cmd_result = a.stdout.read() result_len = bytes(str(len(cmd_result)), ‘utf8‘) conn.sendall(result_len) conn.recv(1024) conn.sendall(cmd_result) # send_data = input(‘input>>‘) # conn.send(bytes(send_data, ‘utf8‘)) conn.close()View Code
client 端:
# _author: lily # _date: 2019/1/26 import socket sk = socket.socket() # print(sk) adress = (‘127.0.0.1‘, 8000) sk.connect(adress) while 1: send_data = input(‘>>‘) if send_data == ‘exit‘: break sk.send(bytes(send_data, ‘utf8‘)) result_len = int(str(sk.recv(1024), ‘utf8‘)) print(result_len) rec_data = bytes() sk.sendall(bytes(‘ok‘, ‘utf8‘)) while len(rec_data) != result_len: rec_data += sk.recv(1024) # 會阻塞,直到收到數據 print(str(rec_data, ‘gbk‘)) sk.close()View Code
ftp 傳輸:
server 端:
# _author: lily # _date: 2019/1/27 import socket import subprocess import os sk = socket.socket() address = (‘127.0.0.1‘, 8000) sk.bind(address) sk.listen(3) print(‘waiting‘) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) while 1: conn, address_client = sk.accept() while 1: data = conn.recv(1024) cmd, filename, filesize = str(data, ‘utf8‘).split(‘|‘) path = os.path.join(BASE_DIR, ‘picture‘, filename) filesize = int(filesize) f = open(path, ‘ab‘) has_receive = 0 while has_receive != filesize: data = conn.recv(1024) f.write(data) has_receive += len(data) f.close() conn.close()View Code
client 端:
# _author: lily # _date: 2019/1/27 import socket import os sk = socket.socket() BASE_DIR = os.path.dirname(os.path.abspath(__file__)) adress = (‘127.0.0.1‘, 8000) sk.connect(adress) while 1: send_data = input(‘>>‘).strip() # post|11.png cmd, path = send_data.split(‘|‘) path = os.path.join(BASE_DIR, path) filename = os.path.basename(path) file_size = os.stat(path).st_size file_info = ‘post|%s|%s‘ % (filename, file_size) sk.sendall(bytes(file_info, ‘utf8‘)) f = open(filename, ‘rb‘) has_sent = 0 while has_sent != file_size: data = f.read(1024) sk.sendall(data) has_sent += len(data) f.close() print(‘success‘) sk.close()View Code
server 下的方法:
bind()
listen()
accept()
recv()
send( string )
sendall()
close()
client 下的方法:
connect()
recv()
send( string )
sendall() # 傳送的類型一定是 byte 類型
close()
25 python 初學(socket,socketserver)