網絡編程小結

1、網絡編程小結

2、網絡架構及其演變過程

2.1 單機架構

不須要聯網shell

2.2 CS架構

客戶端直接和服務端交互編程

2.3 BS架構

客戶端嫁接在瀏覽器上,瀏覽器和服務端交互瀏覽器

3、互聯網和互聯網的組成

3.1 教材版

  1. 邊緣部分:服務端和客戶端
  2. 核心部分:路由器/基站

3.2 科普版

  1. 硬件:網工的事情
  2. 軟件:一大堆協議

4、大白話OSI七層協議

4.1 物理層

硬件,傳輸電信號網絡

4.2 數據鏈路層

對電信號分組架構

以太網頭:head併發

發送地址(mac地址):ssh

接收地址(mac地址):socket

數據類型:tcp

data

mac地址能夠肯定惟一的計算機

4.3 網絡層

對電信號分組

head

以太網頭:

發送地址(ip地址):

接收地址(ip地址):

data

互聯網就是多個局域網,局域網經過路由器鏈接

ip地址+mac地址找到全世界獨一無二的計算機

4.4 傳輸層

找到一個應用程序,每個應用程序都會有一個獨一無二的端口

ip地址+mac地址+端口找到全世界獨一無二的計算機的惟一的應用程序

4.5 應用層

數據交互

5、Socket抽象層

應用程和傳輸層之間,你就是寫了一個應用程序,服務端和客戶端就是一個應用程序

6、TCP協議的三次握手和四次揮手

6.1 三次握手創建鏈接

  1. 客戶端像服務端發出鏈接的帶上SYN的請求給服務端
  2. 服務接收到後,返回一個帶上SYN和ACK的請求給客戶端
  3. 客戶端進入鏈接狀態,而且發送一個帶上ACK的請求給服務端
  4. 服務端收到進入鏈接狀態

6.2 四次揮手斷開鏈接

  1. 客戶端發出帶有FIN的請求給服務端
  2. 服務端返回一個帶有ACK的請求個客戶端,說他已經知道了

而後服務端還有可能會有遺留的數據返回給客戶端,會在這個時候發完

  1. 服務端發完以後纔會發送一個帶有FIN和ACK的請求給客戶端

若是客戶端沒有接收到這條請求,就沒有第四條請求給服務端,服務端會隔一段時間再發一次帶有FIN和ACK的請求給客戶端...若是在2MSL時間內,客戶端一直沒有響應,則強行關閉

  1. 客戶端返回一個帶有ACK請求給服務端,鏈接正常關閉

7、基於TCP協議的socket套接字編程

7.1 服務端

import socket

# 1. 符合TCP協議的手機
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # TCP

# 2. 綁定手機號 110
server.bind(('127.0.0.1', 8000))  # 127.0.0.1表明本地
# server.bind(('192.168.11.210',8000))  # 127.0.0.1表明本地

server.listen(5)  # 半鏈接池

# 3. 等待客戶端鏈接
print('start...')
# 連接循環


while True:
    # 通訊循環
    conn, client_addr = server.accept()
    while True:
        try:
            # 4. 收到消息receive
            data = conn.recv(1024)
            print(data)

            # 5. 回消息
            conn.send(data.upper())
        except ConnectionAbortedError:
            continue
        except ConnectionResetError:
            break

7.2 客戶端

import socket

# 1. 建立符合TCp協議的手機
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 2. 撥號
client.connect(('127.0.0.1',8000))

while True:
    msg = input('please enter your msg')  # dir
    # 3. 發送消息
    client.send(msg.encode('utf8'))

    # 4. 接收消息
    data = client.recv(1024)
    print(data)

8、模擬ssh遠程執行命令

在客戶端處模擬ssh發送指令,服務端經過subprocess執行該命令,而後返回命令的結果

8.1 服務端

import socket
import subprocess

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind(('192.168.11.210', 8000))
server.listen(5)

print('start...')
while True:
    conn, client_addr = server.accept()
    print(client_addr)

    while True:
        try:
            cmd = conn.recv(1024)  # dir
            print(cmd)

            # 幫你執行cmd命令,而後把執行結果保存到管道里
            pipeline = subprocess.Popen(cmd.decode('utf8'),
                                        shell=True,
                                        stderr=subprocess.PIPE,
                                        stdout=subprocess.PIPE)

            stderr = pipeline.stderr.read()
            stdout = pipeline.stdout.read()

            conn.send(stderr)
            conn.send(stdout)

        except ConnectionResetError:
            break

8.2 客戶端

import socket

# 1. 建立符合TCp協議的手機
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 2. 撥號
client.connect(('192.168.11.210',8000))

while True:
    msg = input('please enter your msg')  # dir
    # 3. 發送消息
    client.send(msg.encode('utf8'))

    # 4. 接收消息
    data = client.recv(10)
    print(data.decode('gbk'))

9、粘包問題

  1. 兩個數據很是小,而後間隔時間又短
  2. 數據太大,一次取不完,下一次還會取這個大數據

一10、解決粘包問題

  1. 在傳數據以前,傳一個數據的大小,數據的大小必須得定長

11、基於UDP協議的socket套接字編程

  • UDP無鏈接

11.1 服務端

import socket

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

print('start...')
while True:
    data, client_addr = server.recvfrom(1024)
    print(client_addr)
    print(data)
    server.sendto(data.upper(), client_addr)

11.2 客戶端

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    msg = input('please enter your msg:')
    client.sendto(msg.encode('utf8'), ('127.0.0.1', 8000))

    data = client.recvfrom(1024)
    print(data)

12、基於socketserver實現併發的socket套接字編程

  • 讓服務端同時和多個客戶端進行鏈接,之前咱們寫的是一個警局有五部電話只有一我的,如今寫的是五部電話五我的

12.1 服務端

# 同一時刻有多我的在接聽
import socketserver
import subprocess
import struct


class MyHandler(socketserver.BaseRequestHandler):
    # 通訊循環
    def handle(self):

        while True:
            try:
                cmd = self.request.recv(1024)
                print(cmd)

                pipeline = subprocess.Popen(cmd.decode('utf8'),
                                            shell=True,
                                            stderr=subprocess.PIPE,
                                            stdout=subprocess.PIPE)

                stdout = pipeline.stdout.read()
                stderr = pipeline.stderr.read()

                count_len = len(stdout) + len(stderr)
                guding_bytes = struct.pack('i', count_len)

                self.request.send(guding_bytes)  # 4

                self.request.send(stderr + stdout)

            except ConnectionResetError:
                break


# 使用socketserver的鏈接循環(併發),可是使用了本身的通訊循環
# myhandler = MyHandler()
if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 8000), MyHandler, bind_and_activate=True)
    print('start...')
    server.serve_forever()
相關文章
相關標籤/搜索