網路編程 socket 開發練習題

来源:https://www.cnblogs.com/lys666/archive/2018/12/01/10047382.html
-Advertisement-
Play Games

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # re模塊## 單個匹配\w 匹配字母(包含中文)或數字或下劃線\W 匹配非字母(包含中文)或數字或下劃線```pythonprint(re.findall('\w', 'abc_ 123$%^')) # 返回 ['a', 'b', 'c', '_', '1', '2', '3']print(re... ...
  • 工作中由於業務的限制原因,很少使用JavaIO流,今天剛剛喝完酒,簡單複習一下,用通俗易懂的話語簡單闡述一下本人對IO流的理解,以及使用方法,感興趣的小伙伴們看了覺得還OK希望點個贊喲! IO流分按流向分為輸入流、輸出流 1.輸入流,我們讀取文件內容使用輸入流 2.輸出流,我們把讀取的文件寫入另一個 ...
  • 大二下學期的學習中,讓我無意中瞭解到了python語言,聽說了這門神奇的語言,然後我在大三上學期快期末(就是現在)準備正式開始投入時間精力去瞭解他。 通過網路和資料和自己有一定的c語言基礎的前提下對python也提前進行了簡單的瞭解和理解: python不同於C語言這類很底層的語言,c語言是一種編譯 ...
  • 什麼是跨域?瀏覽器從一個功能變數名稱的網頁去請求另一個功能變數名稱的資源時,功能變數名稱、埠、協議任一不同,都是跨域 。 跨域資源訪問是經常會遇到的場景,當一個資源從與該資源本身所在的伺服器不同的域或埠請求一個資源時,資源便會發起一個跨域 HTTP 請求。出於安全考慮,瀏覽器會限制從腳本內發起的跨域HTTP請求。 ...
  • 精心挑選要閱讀的源碼項目; 飲水思源——官方文檔,先看文檔再看源碼; 下載源碼,安裝到本地,保證能編譯運行; 從巨集觀到微觀,從整體到細節; 找到入口,抓主放次,梳理核心流程; 源碼調試,找到核心數據結構和關鍵類; 勤練習,多折騰; MyBatis 源碼下載地址:https://github.com/ ...
  • 題意 "題目鏈接" Sol 想不到想不到。。 首先在不考慮每個人的真是成績的情況下,設$f[i][j]$表示考慮了前$i$個人,有$j$個人被碾壓的方案數 轉移方程:$$f[i][j] = \sum_{k = j}^n f[i 1][k] C_{k}^{k j} C_{N k}^{r[i] 1 (k ...
  • 1 n=int(input()) 2 if n5: 4 print('ok') 5 else: 6 print('no') 7 else: 8 print('error') ...
  • os模塊,主要提供對操作系統進行調用的介面。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...