第三模块: (2)网络编程基础

计算机基础

应用 -> 控制程序(操作系统) -> 计算机硬件
c/s架构, 通过网络进行通讯。

什么是网络?

OSI七层协议
应用层 表示层 会话层 传输层 传输层 网络层 数据链路层 物理层

五层协议

  • 物理层 电信号
  • 数据链路层
    • 以太网协议(Ethernet)
    • 数据报或数据帧head+data
    • head18个字节(6源地址 6目的地址 6描述data类型)
    • 基于mac地址广播方式, 同一子网内通讯
  • 网络层
    • ip协议
    • ip头+data
    • arp协议: 将ip地址转换为mac地址
  • 传输层
    • tcp/udp
  • 应用层
    • http, ftp

1. 什么是c/s架构?

c/s又称Client/Server服务模式。这种结构的系统把较为复杂的计算和管理任务交给网络上的高档机器,而把频繁与客户打交道的任务交给客户机。任何一个应用系统,不管是简单的单机系统还是复杂的网络系统,都由3个部分组成:显示逻辑部分(表示层)、事务处理逻辑部分(功能层)和数据处理逻辑部分(数据层)。显示逻辑部分的功能是与用户进行交互;事务处理逻辑部分的功能是进行具体的运算和数据的处理;数据处理逻辑部分的功能是对数据库中的数据进行查询、修改和更新等。在两层模式的Client/Server结构中,显示逻辑部分和事务处理逻辑部分均被放在客户端,数据处理逻辑部分和数据库被放在服务器端。这样就使得客户端变得很“胖”,成为胖客户机,而服务器端的任务相对较轻,成为瘦服务器。

2. 互联网协议是什么?分别介绍五层协议中每一层的功能?

互联网协议是网络通信中统一的标准。
五层协议

  • 物理层 主要功能是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0;

  • 数据链路层 主要功能定义了电信号的分组方式。关键字:ethernet,mac, 广播

    以太网协议-MAC地址封装.png

  • 网络层 功能是引入一套新的地址来区分不同的广播域、子网,这套地址即网络地址。关键字:ip协议、子网掩码、ip地址分类、ip报文、arp协议、ICMP、ping、tracetroute

    ip.png

  • 传输层 功能是建立端口到端口的通信,端口范围是0-65535, 0-1023为系统占用端口。传输层有两层层协议:TCP/UDP

    • tcp协议 可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。


      三次握手四次断开.png
    • udp协议, 不可靠传输,”报头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。
  • 应用层

3.基于tcp协议通信,为何建立链接需要三次握手,而断开链接却需要四次挥手?

三次握手

  1. 客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认。
  2. 服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态。
  3. 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=y+1),此包发送完毕,服务端和客户端进入ESTABLISHED状态,完成三次握手。

四次挥手

  1. 主动关闭方发送一个FIN,来关闭到被动关闭方的数据发送。
  2. 被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1
  3. 被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,就是告诉主动关闭方,我的数据也发完了
  4. 主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序列号为收到序号+1

4.为何基于tcp协议的通信比基于udp协议的通信更可靠?

tcp:可靠 对方给了确认收到信息,才发下一个,如果没收到确认信息就重发
udp:不可靠 一直发数据,不需要对方回应

5.流式协议指的是什么协议,数据报协议指的是什么协议?

流式协议:TCP协议,可靠传输
数据报协议: UDP协议,不可传输

6.什么是socket?简述基于tcp协议的套接字通信流程

socket是应用层与TCP/IP协议族通信的中间软件抽象层,他是一组接口。


socket通信流程.png

7.什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?

粘包:数据粘在一起,主要因为:接收方不知道消息之间的界限,不知道一次性提取多少字节的数据造成的
数据量比较小,时间间隔比较短,就合并成了一个包

8.基于socket开发一个聊天程序,实现两端互相发送和接收消息

#!/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,开发简单的远程命令执行程序,允许用户执行命令,并返回结果

#!/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协议编写简单FTP程序,实现上传、下载文件功能,并解决粘包问题

#!/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协议编写程序,实现功能

  • 执行指定的命令,让客户端可以查看服务端的时间
  • 执行指定的命令,让客户端可以与服务的的时间同步
# 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))  # 设置日期
    os.system("time %d:%d:%d.0" % (localtime.tm_hour, localtime.tm_min, localtime.tm_sec))  # 设置时间
 
client.close()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容