1. 程式人生 > >網路程式設計 socket 開發練習題

網路程式設計 socket 開發練習題

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())