1 什麼是C/S架構 c指的是client(客戶端軟體),S指的是Server(服務端軟體),C/S架構的軟體,實現服務端軟體與客戶端軟體基於網路通信 2 互聯網協議是什麼?分別介紹五層協議中每一層的功能 互聯網協議就是電腦界的通訊標準 物理層功能:主要是基於電器特性發送高低電壓(電信號),高電壓 ...
1 什麼是C/S架構
c指的是client(客戶端軟體),S指的是Server(服務端軟體),C/S架構的軟體,實現服務端軟體與客戶端軟體基於網路通信
2 互聯網協議是什麼?分別介紹五層協議中每一層的功能
互聯網協議就是電腦界的通訊標準
物理層功能:主要是基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0
數據鏈路層的功能:定義了電信號的分組方式
網路層功能:引入一套新的地址用來區分不同的廣播域/子網,這套地址即網路地址
傳輸層功能:建立埠到埠的通信 補充:埠範圍0-65535,0-1023為系統占用埠
應用層功能:將應用程式的數據打包傳給傳輸層
3 基於tcp協議通信,為何建立鏈接需要三次握手,而斷開鏈接卻需要四次揮手
三次握手:client發送請求建立通道;server收到請求並同意,同時也發送請求建通道;client收到請求並同意,建立完成
四次揮手:client發送請求斷開通道;server收到請求並同意,但是這時sever可能還在發數據,並不關閉介面,所有回覆同意和發送sever斷開請求不是一同發送的;等到數據發送完畢server也發送請求斷開通道;client受到消息結束
4 為何基於tcp協議的通信比基於udp協議的通信更可靠?
tcp協議是面向鏈接的協議,在通信過程中,雙方通過三次握手建立連接、四次揮手斷開連接,發送方給接收方發送數據,如果沒有得到接收方的回應,就會繼續給它發消息,直到接收方回應。
udp是面向數據報的協議,不需要三次握手建立連接,它不會管接收方有沒有收到數據
5 流式協議指的是什麼協議,數據報協議指的是什麼協議?
流式協議指TCP協議,是通過三次握手建立連接再發送數據的,會存在粘包現象,當發送空消息時,對方並不會收到,不一定是一個send就要對應一個recv,傳輸效率低,網路開銷大,可靠性高。
數據報協議是指UDP協議,是以消息為單位發送的數據的,一個sendto就對應一個recvfrom,不會存在粘包現象,即使發送空消息也能收到,傳輸效率高,網路開銷小,可靠性低。
6 什麼是socket?簡述基於tcp協議的套接字通信流程
socket是介於應用層和傳輸層之間的一組介面。將複雜的TCP/IP協議封裝到介面裡面,使用者只需要知道怎麼用即可,不需要關心底層的實現。
基於TCP的套接字通信流程:
1)服務端:創建一個套接字對象;綁定本機地 址信息;開始時監聽;接收連接;
2)客戶端:創建套接字對象;主動連接客戶端;等待對方接收
通過三次握手後建立連接,開始收發消息。
收發消息完了之後,通過四次揮手斷開連接。
7 什麼是粘包? socket 中造成粘包的原因是什麼? 哪些情況會發生粘包現象?
粘包是指兩次命令執行的結果黏在一起。粘包發生在TCP協議中。
造成粘包的原因:接收方不知道所要接收消息的大小和界限。
發生粘包的情況:1、socket緩衝區導致,socket為了提高傳輸效率,往往會將較短時間間隔內較小的數據包合併發送,這樣接收方就會收到一個粘包數據;
2、接收方不知道該接收多大數據量,當接收方的最大接收量小於消息大小時,會發生粘包。
8 基於socket開發一個聊天程式,實現兩端互相發送和接收消息
import socket sev = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sev.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sev.bind(('127.0.0.1', 9999)) sev.listen(5) print('starting...') while True: conn, client_addr = sev.accept() print(conn) print(client_addr) while True: try: data = conn.recv(1024) print(data.decode()) inp = input('-->').strip() conn.send(inp.encode()) except ConnectionResetError: break conn.close() sev.close()
import socket cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.connect(("127.0.0.1", 9999)) while True: inp = input('---->').strip() if not inp: continue cli.send(inp.encode()) data = cli.recv(1024) print(data.decode()) cli.close()
9 基於tcp socket,開發簡單的遠程命令執行程式,允許用戶執行命令,並返回結果
import socket import subprocess import json import struct sev = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sev.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sev.bind(('127.0.0.1', 5555)) sev.listen(5) print('start'.center(50, '-')) while True: conn, addr = sev.accept() while True: try: cmd = conn.recv(1024) obj = subprocess.Popen(cmd.decode(), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = obj.stdout.read() stderr = obj.stderr.read() total_size = len(stdout)+len(stderr) dict_msg = {'file_name': 'a.txt', 'md5': 12431564, 'total_size': total_size} dict_bytes = json.dumps(dict_msg).encode() header = struct.pack('i', len(dict_bytes))[0] conn.send(header) conn.send(dict_bytes) conn.send(stdout) conn.send(stderr) except ConnectionResetError: break conn.close() sev.close()
import socket import struct import json cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.connect(('127.0.0.1', 5555)) while True: cmd = input('-->') if not cmd: continue cli.send(cmd.encode()) obj = cli.recv(4) header_len = struct.unpack('i', obj)[0] header = cli.recv(header_len) dict_msg = json.loads(header.decode()) total_size = dict_msg['total_size'] recv_size = 0 recv_data = b'' while recv_size < total_size: data = cli.recv(1024) recv_size += len(data) recv_data += data print(recv_data.decode('gbk')) cli.close()
10 基於tcp協議編寫簡單FTP程式,實現上傳、下載文件功能,並解決粘包問題
import json import socket import os import struct BASE_DIR = os.path.dirname(os.path.abspath(__name__)) SHARE_PATH = os.path.join(BASE_DIR, 'share') print(SHARE_PATH) class Sever(): def __init__(self): print('start....') self.ser = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.ser.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.ser.bind(('127.0.0.1', 9999)) self.ser.listen(5) self.run() def run(self): while True: self.conn, self.client_addr = self.ser.accept() while True: try: cmd_b = self.conn.recv(1024) cmd, file_name = cmd_b.decode().split() if hasattr(self, cmd): func = getattr(self, cmd) func(file_name) else: print('none...') except ConnectionResetError: break def get(self, file_name): '''客戶端下載''' if os.path.exists('%s\%s' % (SHARE_PATH, file_name)): file_size = os.path.getsize('%s\%s' % (SHARE_PATH, file_name)) dict_msg = {'file_name': file_name, 'md5': 124521, 'file_size': file_size, 'file': True} header = json.dumps(dict_msg).encode() header_size = len(header) self.conn.send(struct.pack('i', header_size)) self.conn.send(header) with open('%s\%s' % (SHARE_PATH, file_name), 'rb') as f: for line in f: self.conn.send(line) else: print('send has done...') else: dict_msg = {'file_name': file_name, 'md5': 124521, 'file_size': None, 'file': False} header = json.dumps(dict_msg).encode() header_size = len(header) self.conn.send(struct.pack('i', header_size)) self.conn.send(header) print('file not exist') def put(self, file_name): '''客戶端上傳''' obj = self.conn.recv(4) header_len = struct.unpack('i', obj)[0] header = self.conn.recv(header_len) dict_msg = json.loads(header.decode()) file_size = dict_msg['file_size'] with open('%s\%s' % (SHARE_PATH, file_name), 'wb')as f: recv_size = 0 while recv_size < file_size: data = self.conn.recv(1024) f.write(data) recv_size += len(data) print("%s 接受完成" % file_name) sever = Sever()
import socket import json import struct import os BASE_DIR = os.path.dirname(os.path.abspath(__name__)) DOWMLOAD_PATH = os.path.join(BASE_DIR, 'download') class Client(): def __init__(self): self.cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.cli.connect(("127.0.0.1", 9999)) print('go....') while True: inp = input('-->').strip() if not inp: continue try: cmd, file_name = inp.split() except ValueError: print('輸入不合法') continue self.cli.send(inp.encode()) if hasattr(self, cmd): func = getattr(self, cmd) func(file_name) def get(self,file_name): obj = self.cli.recv(4) header_size = struct.unpack('i', obj)[0] header = self.cli.recv(header_size) dict_msg = json.loads(header.decode()) if dict_msg['file']: file_size = dict_msg['file_size'] recv_size = 0 with open("%s\%s" % (DOWMLOAD_PATH, file_name), 'wb')as f: while recv_size < file_size: data = self.cli.recv(1024) f.write(data) recv_size += len(data) print('%s 下載完成 ' % file_name) else: print('%s 不存在 ' % file_name) def put(self,file_name): if os.path.exists('%s\%s' % (DOWMLOAD_PATH, file_name)): file_size = os.path.getsize('%s\%s' % (DOWMLOAD_PATH, file_name)) dict_msg = {'file_name': file_name, 'md5': 124521, 'file_size': file_size, 'file': True} header = json.dumps(dict_msg).encode() header_size = len(header) self.cli.send(struct.pack('i', header_size)) self.cli.send(header) with open('%s\%s' % (DOWMLOAD_PATH, file_name), 'rb') as f: for line in f: self.cli.send(line) else: print('send has done...') else: print('file not exist')
11 基於udp協議編寫程式,實現功能
import socket sev = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sev.bind(('127.0.0.1', 9999)) print('start...') while True: msg, client_addr = sev.recvfrom(1024) print(msg.decode()) inp = input('-->').strip().encode() sev.sendto(inp, client_addr)
import socket cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True: inp = input('-->').strip() cli.sendto(inp.encode(), ('127.0.0.1', 9999)) msg, sever_addr =cli.recvfrom(1024) print(msg.decode())