第三模塊: (2)網(wǎng)絡(luò)編程基礎(chǔ)

計算機基礎(chǔ)

應(yīng)用 -> 控制程序(操作系統(tǒng)) -> 計算機硬件
c/s架構(gòu)舟舒, 通過網(wǎng)絡(luò)進行通訊。

什么是網(wǎng)絡(luò)?

OSI七層協(xié)議
應(yīng)用層 表示層 會話層 傳輸層 傳輸層 網(wǎng)絡(luò)層 數(shù)據(jù)鏈路層 物理層

五層協(xié)議

  • 物理層 電信號
  • 數(shù)據(jù)鏈路層
    • 以太網(wǎng)協(xié)議(Ethernet)
    • 數(shù)據(jù)報或數(shù)據(jù)幀head+data
    • head18個字節(jié)(6源地址 6目的地址 6描述data類型)
    • 基于mac地址廣播方式, 同一子網(wǎng)內(nèi)通訊
  • 網(wǎng)絡(luò)層
    • ip協(xié)議
    • ip頭+data
    • arp協(xié)議: 將ip地址轉(zhuǎn)換為mac地址
  • 傳輸層
    • tcp/udp
  • 應(yīng)用層
    • http现斋, ftp

1. 什么是c/s架構(gòu)?

c/s又稱Client/Server服務(wù)模式解取。這種結(jié)構(gòu)的系統(tǒng)把較為復(fù)雜的計算和管理任務(wù)交給網(wǎng)絡(luò)上的高檔機器步责,而把頻繁與客戶打交道的任務(wù)交給客戶機。任何一個應(yīng)用系統(tǒng),不管是簡單的單機系統(tǒng)還是復(fù)雜的網(wǎng)絡(luò)系統(tǒng)蔓肯,都由3個部分組成:顯示邏輯部分(表示層)遂鹊、事務(wù)處理邏輯部分(功能層)和數(shù)據(jù)處理邏輯部分(數(shù)據(jù)層)。顯示邏輯部分的功能是與用戶進行交互蔗包;事務(wù)處理邏輯部分的功能是進行具體的運算和數(shù)據(jù)的處理秉扑;數(shù)據(jù)處理邏輯部分的功能是對數(shù)據(jù)庫中的數(shù)據(jù)進行查詢、修改和更新等调限。在兩層模式的Client/Server結(jié)構(gòu)中舟陆,顯示邏輯部分和事務(wù)處理邏輯部分均被放在客戶端,數(shù)據(jù)處理邏輯部分和數(shù)據(jù)庫被放在服務(wù)器端耻矮。這樣就使得客戶端變得很“胖”秦躯,成為胖客戶機,而服務(wù)器端的任務(wù)相對較輕裆装,成為瘦服務(wù)器踱承。

2. 互聯(lián)網(wǎng)協(xié)議是什么?分別介紹五層協(xié)議中每一層的功能哨免?

互聯(lián)網(wǎng)協(xié)議是網(wǎng)絡(luò)通信中統(tǒng)一的標(biāo)準(zhǔn)茎活。
五層協(xié)議

  • 物理層 主要功能是基于電器特性發(fā)送高低電壓(電信號),高電壓對應(yīng)數(shù)字1琢唾,低電壓對應(yīng)數(shù)字0载荔;

  • 數(shù)據(jù)鏈路層 主要功能定義了電信號的分組方式。關(guān)鍵字:ethernet,mac, 廣播

    以太網(wǎng)協(xié)議-MAC地址封裝.png

  • 網(wǎng)絡(luò)層 功能是引入一套新的地址來區(qū)分不同的廣播域采桃、子網(wǎng)懒熙,這套地址即網(wǎng)絡(luò)地址。關(guān)鍵字:ip協(xié)議芍碧、子網(wǎng)掩碼煌珊、ip地址分類号俐、ip報文泌豆、arp協(xié)議、ICMP吏饿、ping踪危、tracetroute

    ip.png

  • 傳輸層 功能是建立端口到端口的通信,端口范圍是0-65535猪落, 0-1023為系統(tǒng)占用端口贞远。傳輸層有兩層層協(xié)議:TCP/UDP

    • tcp協(xié)議 可靠傳輸,TCP數(shù)據(jù)包沒有長度限制笨忌,理論上可以無限長蓝仲,但是為了保證網(wǎng)絡(luò)的效率,通常TCP數(shù)據(jù)包的長度不會超過IP數(shù)據(jù)包的長度,以確保單個TCP數(shù)據(jù)包不必再分割袱结。


      三次握手四次斷開.png
    • udp協(xié)議亮隙, 不可靠傳輸,”報頭”部分一共只有8個字節(jié)垢夹,總長度不超過65,535字節(jié)溢吻,正好放進一個IP數(shù)據(jù)包。
  • 應(yīng)用層

3.基于tcp協(xié)議通信果元,為何建立鏈接需要三次握手促王,而斷開鏈接卻需要四次揮手?

三次握手

  1. 客戶端發(fā)送syn包(syn=x)到服務(wù)器而晒,并進入SYN_SEND狀態(tài)蝇狼,等待服務(wù)器確認。
  2. 服務(wù)器收到syn包倡怎,必須確認客戶的SYN(ack=x+1)题翰,同時自己也發(fā)送一個SYN包(syn=y),即SYN+ACK包诈胜,此時服務(wù)器進入SYN_RECV狀態(tài)豹障。
  3. 客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認包ACK(ACK=y+1)焦匈,此包發(fā)送完畢血公,服務(wù)端和客戶端進入ESTABLISHED狀態(tài),完成三次握手缓熟。

四次揮手

  1. 主動關(guān)閉方發(fā)送一個FIN累魔,來關(guān)閉到被動關(guān)閉方的數(shù)據(jù)發(fā)送。
  2. 被動關(guān)閉方收到FIN包后够滑,發(fā)送一個ACK給對方垦写,確認序號為收到序號+1
  3. 被動關(guān)閉方發(fā)送一個FIN,用來關(guān)閉被動關(guān)閉方到主動關(guān)閉方的數(shù)據(jù)傳送彰触,就是告訴主動關(guān)閉方梯投,我的數(shù)據(jù)也發(fā)完了
  4. 主動關(guān)閉方收到FIN后,發(fā)送一個ACK給被動關(guān)閉方况毅,確認序列號為收到序號+1

4.為何基于tcp協(xié)議的通信比基于udp協(xié)議的通信更可靠分蓖?

tcp:可靠 對方給了確認收到信息,才發(fā)下一個尔许,如果沒收到確認信息就重發(fā)
udp:不可靠 一直發(fā)數(shù)據(jù)么鹤,不需要對方回應(yīng)

5.流式協(xié)議指的是什么協(xié)議,數(shù)據(jù)報協(xié)議指的是什么協(xié)議味廊?

流式協(xié)議:TCP協(xié)議蒸甜,可靠傳輸
數(shù)據(jù)報協(xié)議: UDP協(xié)議棠耕,不可傳輸

6.什么是socket?簡述基于tcp協(xié)議的套接字通信流程

socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層柠新,他是一組接口昧辽。


socket通信流程.png

7.什么是粘包? socket 中造成粘包的原因是什么登颓? 哪些情況會發(fā)生粘包現(xiàn)象搅荞?

粘包:數(shù)據(jù)粘在一起,主要因為:接收方不知道消息之間的界限框咙,不知道一次性提取多少字節(jié)的數(shù)據(jù)造成的
數(shù)據(jù)量比較小咕痛,時間間隔比較短,就合并成了一個包

8.基于socket開發(fā)一個聊天程序喇嘱,實現(xiàn)兩端互相發(fā)送和接收消息

#!/usr/bin/env python3
# Author    : fbo
# @Time : 18-5-7 下午8:27
# @File : sever.py

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', 8080))
server.listen(5)

print('Starting...')

while True:
    conn, addr = server.accept()
    while True:
        data = conn.recv(1024)
        if not data:
            break
        print("%s: %s" % (addr[0], data.decode('utf-8')))
        msg = input(">>>:").strip()
        if not msg:
            continue
        conn.send(msg.encode('utf-8'))
    conn.close()
server.close()

#!/usr/bin/env python3
# Author    : fbo
# @Time : 18-5-7 下午8:28
# @File : client.py

import socket

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

client.connect(('127.0.0.1', 8080))

while True:
    msg = input(">>>: ").strip()
    if not msg:
        continue
    client.send(msg.encode('utf-8'))
    data = client.recv(1024)
    print(data.decode('utf-8'))

9.基于tcp socket茉贡,開發(fā)簡單的遠程命令執(zhí)行程序,允許用戶執(zhí)行命令者铜,并返回結(jié)果

#!/usr/bin/env python3
# Author    : fbo
# @Time : 18-5-7 下午8:27
# @File : sever.py

import socket
import subprocess

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', 8080))
server.listen(5)

print('Staring...')

while True:
    conn, addr = server.accept()
    while True:
        data = conn.recv(1024)
        if not data:
            break
        obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr= subprocess.PIPE)
        conn.send(obj.stdout.read())
        conn.send(obj.stderr.read())
    conn.close()
server.close()

#!/usr/bin/env python3
# Author    : fbo
# @Time : 18-5-7 下午8:28
# @File : client.py

import socket

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

client.connect(('127.0.0.1', 8080))

while True:
    msg = input(">>>: ").strip()
    if not msg:
        continue
    client.send(msg.encode('utf-8'))
    data = client.recv(1024)
    print(data.decode('utf-8'))

10. 基于tcp協(xié)議編寫簡單FTP程序腔丧,實現(xiàn)上傳、下載文件功能作烟,并解決粘包問題

#!/usr/bin/env python3
# Author    : fbo
# @Time : 18-5-7 下午8:27
# @File : sever.py

import struct
import json
import socket
from os import path

file_dir = path.join(path.dirname(__file__), 'data')

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', 8080))
server.listen(5)

print('Staring...')

def pack_header(data, filename):
    header = {
        'file_name': path.split(filename)[1],
        'data_size': len(data),
        'exists': path.isfile(filename),
    }
    json_header = json.dumps(header).encode('utf-8')
    header_len = struct.pack('i', len(json_header))
    return header_len, json_header


while True:
    conn, addr = server.accept()
    while True:
        cmd = conn.recv(1024)
        if not cmd:
            break
        command = cmd.decode('utf-8').split()
        if command[0] == 'get':
            file = command[1]
            filename = path.join(file_dir, file)
            if path.isfile(filename):
                with open(filename, 'rb') as f:
                    data= f.read()
            else:
                data = '%s not exists...' % file
                data = data.encode('utf-8')
            p_header = pack_header(data, filename)
            conn.send(p_header[0])
            conn.send(p_header[1])
            conn.send(data)
        elif command[0] == 'put':
            print(123)
            header_len = struct.unpack('i', conn.recv(4))[0]
            print(header_len)
            json_header = conn.recv(header_len)
            print(json_header)
            header = json.loads(json_header.decode('utf-8'))
            file = path.split(header['file_name'])[1]
            data_size = header['data_size']
            size = 0
            filename = path.join(file_dir, file)
            with open(filename, 'wb') as f:
                while size < data_size:
                    data = conn.recv(1024)
                    f.write(data)
                    size += len(data)
    conn.close()
server.close()

#!/usr/bin/env python3
# Author    : fbo
# @Time : 18-5-7 下午8:28
# @File : client.py

import struct
import json
import socket
from os import path

file_dir = path.join(path.dirname(__file__), 'data')

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

client.connect(('127.0.0.1', 8080))

def pack_header(data, filename):
    header = {
        'file_name': path.split(filename)[1],
        'data_size': len(data),
        'exists': path.isfile(filename),
    }
    json_header = json.dumps(header).encode('utf-8')
    header_len = struct.pack('i', len(json_header))
    return header_len, json_header


while True:
    msg = input(">>>: ").strip()
    if not msg:
        continue
    if msg.startswith('get'):
        client.send(msg.encode('utf-8'))
        header_len = struct.unpack('i', client.recv(4))[0]
        json_header = client.recv(header_len)
        header = json.loads(json_header.decode('utf-8'))
        file = path.split(header['file_name'])[1]
        data_size = header['data_size']
        size = 0
        filename = path.join(file_dir, file)
        if header['exists']:
            with open(filename, 'wb') as f:
                while size < data_size:
                    data = client.recv(1024)
                    f.write(data)
                    size += len(data)
        else:
            data = client.recv(1024).decode('utf-8')
            print(data)
    elif msg.startswith('put'):
        client.send(msg.encode('utf-8'))
        command = msg.split()
        file = command[1]
        filename = path.join(file_dir, file)
        if path.isfile(filename):
            with open(filename, 'rb') as f:
                data = f.read()
            p_header = pack_header(data, filename)
            client.send(p_header[0])
            client.send(p_header[1])
            client.send(data)
        else:
            print('%s not exists...' % file)

client.close()

11. 基于udp協(xié)議編寫程序愉粤,實現(xiàn)功能

  • 執(zhí)行指定的命令,讓客戶端可以查看服務(wù)端的時間
  • 執(zhí)行指定的命令拿撩,讓客戶端可以與服務(wù)的的時間同步
# sever.py
# _*_ coding: utf-8 _*_
import socket
import subprocess
import time
 
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
    data, client_addr = server.recvfrom(1024)
    print(data, client_addr)
    obj = subprocess.Popen(data.decode('utf-8'),shell=True,  # time 命令在windows 下不能用
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)
    stdout = obj.stdout.read()
    stderr = obj.stderr.read()
    print(stdout+stderr)
    server.sendto(stdout+stderr,client_addr)
    if data.decode('utf-8') == 'time':
        str_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        # str_time = '2017-01-01 00:00:00'
        server.sendto(str_time.encode('gbk'), client_addr)
 
server.close()

# client.py
# _*_ coding: utf-8 _*_
import socket
import os
import time
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    msg = input('>>>:').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
    data,server_addr = client.recvfrom(1024)
    print(data.decode('utf-8'),server_addr)
    localtime = time.localtime()
    os.system("date %d-%d-%d" % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday))  # 設(shè)置日期
    os.system("time %d:%d:%d.0" % (localtime.tm_hour, localtime.tm_min, localtime.tm_sec))  # 設(shè)置時間
 
client.close()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末衣厘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子压恒,更是在濱河造成了極大的恐慌影暴,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件探赫,死亡現(xiàn)場離奇詭異型宙,居然都是意外死亡,警方通過查閱死者的電腦和手機伦吠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門妆兑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人讨勤,你說我怎么就攤上這事箭跳〕苛恚” “怎么了潭千?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長借尿。 經(jīng)常有香客問我刨晴,道長屉来,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任狈癞,我火速辦了婚禮茄靠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝶桶。我一直安慰自己慨绳,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布真竖。 她就那樣靜靜地躺著脐雪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恢共。 梳的紋絲不亂的頭發(fā)上战秋,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音讨韭,去河邊找鬼脂信。 笑死,一個胖子當(dāng)著我的面吹牛透硝,可吹牛的內(nèi)容都是我干的狰闪。 我是一名探鬼主播灵汪,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼杜秸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了夫凸?” 一聲冷哼從身側(cè)響起甜攀,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤秋泄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后规阀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恒序,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年谁撼,在試婚紗的時候發(fā)現(xiàn)自己被綠了歧胁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡厉碟,死狀恐怖喊巍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情箍鼓,我是刑警寧澤崭参,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站款咖,受9級特大地震影響何暮,放射性物質(zhì)發(fā)生泄漏奄喂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一海洼、第九天 我趴在偏房一處隱蔽的房頂上張望跨新。 院中可真熱鬧,春花似錦坏逢、人聲如沸域帐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俯树。三九已至,卻和暖如春贰盗,著一層夾襖步出監(jiān)牢的瞬間许饿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工舵盈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留陋率,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓秽晚,卻偏偏與公主長得像瓦糟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赴蝇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容