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

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。