網絡編程 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())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM