Python網絡練習題

 

練習題

  1. 什麼是C/S架構?python

      
    C/S架構客戶端、服務端架構,C/S端軟件主要有網絡遊戲,QQ等

     

  2. 互聯網協議是什麼?分別介紹五層協議中每一層的功能?算法

      互聯網協議:計算機之間的通訊標準
    物理層:主要是基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0。原始比特流在物理介質上的傳輸。
    數據鏈路層:定義電信號的分組方式,兩臺主機經過MAC地址進行通訊。
    網絡層:引入IP地址區分不一樣的廣播/子網,選擇正確的路由找到目標主機。
    傳輸層:創建端口到端口的通訊,TCP,UDP。
    應用層:供操做系統或應用進行網絡通訊的標準接口(FTP,HTTP,TELNET)

     

  3. 基於tcp協議通訊,爲什麼創建連接須要三次握手,而斷開連接卻須要四次揮手shell

      由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四次揮手.

     

  4. 爲什麼基於tcp協議的通訊比基於udp協議的通訊更可靠?編程

      TCP協議的通訊是面向鏈接的協議,只要不獲得確認,就從新發送數據報,直到獲得對方的確認爲止。
    UDP協議的通訊它是面向非鏈接的協議,它不與對方創建鏈接,而是直接就把數據包發送過去。

     

  5. ‍流式協議指的是什麼協議,數據報協議指的是什麼協議?json

      
    流式協議指TCP
    數據報協議指UDP

     

  6. 什麼是socket?簡述基於tcp協議的套接字通訊流程windows

      
    socket是應用層與TCP/IP協議通訊的中間軟件抽象層,它是一組接口。它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來講,一組簡單的接口就是所有,讓Socket去組織數據,以符合指定的協議。
    因此,咱們無需深刻理解tcp/udp協議,socket已經爲咱們封裝好了,咱們只須要遵循socket的規定去編程,寫出的程序天然就是遵循tcp/udp標準的。

     

  7. 什麼是粘包? socket 中形成粘包的緣由是什麼? 哪些狀況會發生粘包現象?服務器

      TCP協議是面向流的協議,客戶端把多個數據包合併在一塊兒發送到服務端,就產生了粘包。
    因爲接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所形成的。
    只有TCP有粘包現象,UDP永遠不會粘包

    客戶端粘包:
    發送端須要等緩衝區滿才發送出去,形成粘包(發送數據時間間隔很短,數據量很小,TCP優化算法會當作一個包發出去,產生粘包)

    服務端粘包:
    接收方不及時接收緩衝區的包,形成多個包接收(客戶端發送了一段數據,服務端只收了一小部分,服務端下次再收的時候仍是從緩衝區拿上次遺留的數據,產生粘包) 

     

  8. 基於socket開發一個聊天程序,實現兩端互相發送和接收消息
server.py


import socket

IP_PORT = ('127.0.0.1', 9999)
sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.bind(IP_PORT)

sock_server.listen(5)
print("start ……")
while True:
    conn, addr = sock_server.accept()  # 阻塞直到有鏈接爲止
    print('connect by ', addr)
    while True:
        try:
            data = conn.recv(1024)  # 收到數據
            if not data:
                break
            print('server 收到的數據 ', data.decode())
            response = input(" input server msg >>> ").strip()
            conn.send(response.encode())
            print("send to data:", response)

        except ConnectionResetError:  # 適用於windows操做系統,防止客戶端斷開鏈接後死循環
            break
    conn.close()

sock_server.close()

-----------------------------------------------------------------------
client.py

import socket

client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP_PORT = ('127.0.0.1', 9999)
client_sock.connect(IP_PORT)

while True:
    msg = input(" input client msg >>> ").strip()
    if not msg:
        continue
    client_sock.send(msg.encode())  # 發送用戶輸入的數據,必須是bytes模式
    recv_data = client_sock.recv(1024)
    print('client recvive data ', recv_data.decode())  # 收到服務器的響應後

  

9. 基於tcp socket,開發簡單的遠程命令執行程序,容許用戶執行命令,並返回結果網絡

server:
  
import socket
import subprocess
import struct
import json

def cmd_exec(cmd):
    """
    執行shell命令
    :param cmd:
    :return:
    """
    p = subprocess.Popen(cmd, shell=True,
                         stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        return stderr
    return stdout


IP_PORT = ('127.0.0.1', 9999)
sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.bind(IP_PORT)

sock_server.listen(5)
print("start ……")
while True:
    conn, addr = sock_server.accept()  # 阻塞直到有鏈接爲止
    print('connect by ', addr)
    while True:
        try:
            data = conn.recv(1024)  # 收到數據
            if not data:
                break
            print('客戶端的命令', data.decode('GBK'))
            res = cmd_exec(data.decode('GBK'))  # 執行cmd命令
            # 構造消息頭,命令+結果長度,防止粘包
            header = {
                'cmd': data.decode('GBK'),
                'res_size': len(res)
            }
            header_json = json.dumps(header)
            header_bytes = header_json.encode('utf-8')

            header = struct.pack('i', len(header_bytes))
            #  第二步:把報頭長度發送給客戶端
            conn.send(header)
            #  第三步:把報頭內容發送給客戶端
            conn.send(header_bytes)

            # 第四步:再發送真實的數據
            conn.sendall(res)

        except ConnectionResetError:  # 適用於windows操做系統,防止客戶端斷開鏈接後死循環
            break
    conn.close()

sock_server.close()


--------------------------------------

client:
  
import socket
import struct
import json

client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP_PORT = ('127.0.0.1', 9999)
client_sock.connect(IP_PORT)

while True:
    msg = input(" input client msg >>> ").strip()
    if not msg:
        continue
    client_sock.send(msg.encode('GBK'))  # 發送數據

    # 第一步:先收報頭
    header = client_sock.recv(4)
    # 第二步:從報頭中解析(header數據的長度)
    header_size = struct.unpack('i', header)[0]
    print('收到報頭長度=', header_size)
    # 第三步:收到報頭解析出對真實數據的描述信息
    header_json = client_sock.recv(header_size)
    header_dict = json.loads(header_json)
    print('收到報頭內容=', header_dict)
    total_size = header_dict['res_size']

    # 第三步:接收真實的數據
    recv_size = 0
    recv_data = b''

    while recv_size < total_size:
        data = client_sock.recv(1024)
        recv_data += data
        recv_size += len(data)

        print('接收數據 =', recv_data.decode('gbk', 'ignore'))  # 若是設置爲ignore,則會忽略非法字符;

client_sock.close()

  

10. 基於tcp協議編寫簡單FTP程序,實現上傳、下載文件功能,並解決粘包問題架構

11. 基於udp協議編寫程序,實現功能socket

      1. 執行指定的命令,讓客戶端能夠查看服務端的時間

      2. 執行指定的命令,讓客戶端能夠與服務的的時間同步

server:

from socket import *
import time
import struct
import json


server = socket(AF_INET, SOCK_DGRAM)
server.bind(('127.0.0.1', 8880))

while True:
    print("waiting for message ……")
    # 收到報頭長度
    action_type, client = server.recvfrom(1024)
    print('recv {}'.format(action_type.decode()))
    if not action_type:
        print('connect is lost ……')
        break
    if action_type:
        print('start sent to server time ……')
        server_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        time.sleep(1)
        server.sendto(server_time.encode('utf-8'), client)

server.close()

--------------------------------------------------------
client:

from socket import *
import time
import json
import struct


def send_msg(client, action_type, **kwargs):
    """
     打包消息,發送到服務器
    :param action_type:
    :param kwargs:
    :return:
    """

    # 發送cmd
    print('發送auth報頭內容:{}'.format(action_type))
    client.sendto(action_type.encode("utf-8"), ('127.0.0.1',8880))


if __name__ == '__main__':

    client = socket(AF_INET, SOCK_DGRAM)

    while True:
        cmd = input("input cmd >> ").strip()
        if not cmd: continue
        send_msg(client, cmd)
        data, server = client.recvfrom(1024)
        if cmd =='gettime':
            print("server time is", data.decode())
            print("local clock is", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        elif cmd == 'synctime':
            print("server time is {} start sync client clock ……".format(data.decode()))
            print("local clock is", data.decode())
        elif cmd == 'bye':
            break
        else:
            print('input cmd error')
    client.close()
相關文章
相關標籤/搜索