zoukankan      html  css  js  c++  java
  • python网络编程01

    1、什么是C/S架构?

    客户端/服务器架构。实现服务端软件与客户端软件基于网络的通信。

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

    互联网协议是指用于互联网通信的规范。分为:osi七层、tcp/ip五层、tcp/ip四层

    物理层:基于电气特性发送高低电压,高电压用1,低电压用0

    数据链路层:通过Ethernet协议标准将电信号进行分组

    网络层:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址

    传输层:建立端口到端口的通信,使用TCP/UDP协议

    应用层:发起请求,使用http/ftp/自定义协议

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

    三次握手:首先客户端给服务端发送一个syn包请求连接;服务端收到之后会对客户端的请求作出回应,发送一个ack包给客户端,并且同时将一个syn包发送给客户端请求连接,即发送syn包+ack包;客户端收到syn包+ack包之后,对服务端的请求作出确认,发送一个ack包给服务端,此时,完成三次握手,客户端和服务端开始收发数据。

    断开连接的时候,TCP也需要互相确认才可以断开连接,采用四次挥手断开一个连接,客户端如果发送完数据,就给服务端发送一个断开连接的请求,服务端收到请求后,给客户端发送一个确认信息,服务端接收完数据之后给客户端发送断开连接的请求,客户端收到消息后给服务端发送一个确认消息,至此,连接断开。

    这样做的原因是,两端数据的接收并不是同时进行的,数据大小也不一样,如果三次挥手有可能导致一端的数据接收不完整。

    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
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
    server.bind(("127.0.0.1", 8080))
    server.listen(5)
    print("starting.....")
    while True:
        conn, client_addr = server.accept()
        if not conn:
            break
        while True:
            msg = conn.recv(1024)
            print("from aa:", msg.decode())
            if msg.decode() == "bye":
                break
            inp = input("me:").strip()
            conn.send(inp.encode())
        conn.close()
    server.close()
    
    
    # 客户端
    import socket
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    client.connect(("127.0.0.1", 8080))
    while True:
        msg = input("me:").strip()
        client.send(msg.encode())
        if msg == "bye":
            break
        msg1 = client.recv(1024)
        print("from xx:", msg1.decode())
        
    client.close()
    View Code

    9、基于tcp socket,开发简单的远程命令执行程序,允许用户执行命令,并返回结果

    # 服务端
    import socket
    import subprocess
    import struct
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(("127.0.0.1", 8080))
    s.listen(3)
    while True:
        print("starting....")
        conn,addr = s.accept()
        if not conn:
            break
        while True:
            cmd = conn.recv(1024).decode()
            if not cmd:
                break
            res = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE, shell=True)
            stdout = res.stdout.read()
            stderr = res.stderr.read()
            res_len = len(stdout)+len(stderr)
            len_struct = struct.pack("i", res_len)
            conn.send(len_struct)
            conn.send(stdout)
            conn.send(stderr)
        conn.close()
    s.close()
    
    
    # 客户端
    import socket
    import struct
    c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    c.connect(("127.0.0.1", 8080))
    while True:
        cmd = input("input command:").strip()
        c.send(cmd.encode())
        if not cmd:
            break
        header = c.recv(4)
        header_len = struct.unpack("i", header)[0]
        res = c.recv(header_len)
        print("command results:", res.decode("gbk"))
    c.close()
    View Code

    10、基于tcp协议编写简单FTP程序,实现上传、下载文件功能,并解决粘包问题

    # 服务端
    import socket
    import os
    import json
    import struct
    
    
    class Server:
        host = "127.0.0.1"
        port = 8080
        max_recv = 512
        serverfile = r"D:code2ex删除文件传输serverserverfile"
    
        def __init__(self):
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.sock.bind((self.host, self.port))
            self.sock.listen(2)
    
        def get(self, filename):
            """下载文件
            制作报头,json,拿到报头大小,压缩报头长度为4,发送报头长度,发送报头,发送文件"""
            header_dic = {"filename": filename,
                          "md5": "xxx",
                          "file_size": os.path.getsize(os.path.join(self.serverfile, filename))}
            header_bytes = json.dumps(header_dic).encode()
            header_len = len(header_bytes)
            header_struct = struct.pack("i", header_len)
            self.conn.send(header_struct)
            self.conn.send(header_bytes)
            with open(os.path.join(self.serverfile, filename), "rb") as f:
                for line in f:
                    self.conn.send(line)
    
        def put(self, filename):
            """上传文件
            拿到报头长度,解压报头长度,接收报头,json,拿到文件大小,接收文件"""
            header_struct = self.conn.recv(4)
            header_len = struct.unpack("i", header_struct)[0]
            header_bytes = self.conn.recv(header_len)
            header_dic = json.loads(header_bytes.decode())
            file_size = header_dic["file_size"]
            recv_size = 0
            with open(os.path.join(self.serverfile, filename), "wb") as f:
                while recv_size < file_size:
                    content = self.conn.recv(self.max_recv)
                    f.write(content)
                    recv_size += len(content)
    
        def run(self):
            while True:
                print("starting....")
                self.conn,self.addr = self.sock.accept()
                if not self.conn:
                    break
                while True:
                    cmd = self.conn.recv(self.max_recv).decode()
                    if not cmd:
                        break
                    cmds = cmd.strip().split()
                    if hasattr(self, cmds[0]):
                        func = getattr(self, cmds[0])
                        func(cmds[1])
                self.conn.close()
            self.sock.close()
    
    
    server = Server()
    if __name__ == "__main__":
        server.run()
    
    
    # 客户端
    import socket
    import os
    import json
    import struct
    
    
    class Client:
        host = "127.0.0.1"
        port = 8080
        max_recv = 512
        localfile = r"D:code2ex删除文件传输clientlocalfile"
    
        def __init__(self):
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect((self.host, self.port))
    
        def get(self, filename):
            """下载文件
            接收报头大小,解压报头大小,接收报头,json,
            拿到文件大小,接收文件,存储文件
            """
            header_struct = self.sock.recv(4)
            header_len = struct.unpack("i", header_struct)[0]
            header_bytes = self.sock.recv(header_len)
            header_dic = json.loads(header_bytes.decode())
            file_size = header_dic["file_size"]
            recv_size = 0
            with open(os.path.join(self.localfile, filename), "wb") as f:
                while recv_size < file_size:
                    content = self.sock.recv(self.max_recv)
                    f.write(content)
                    recv_size += len(content)
                print("下载成功!")
    
        def put(self, filename):
            """上传文件
            制作报头,json,压缩报头长度,发送报头长度,发送报头,发送文件"""
            header_dic = {"filename": filename,
                          "md5":"xxxx",
                          "file_size":os.path.getsize(os.path.join(self.localfile, filename))}
            header_bytes = json.dumps(header_dic).encode()
            header_len = len(header_bytes)
            header_struct = struct.pack("i", header_len)
            self.sock.send(header_struct)
            self.sock.send(header_bytes)
            with open(os.path.join(self.localfile, filename), "rb") as f:
                for line in f:
                    self.sock.send(line)
            print("上传成功!")
    
        def run(self):
            while True:
                cmd = input("input command:").strip()
                if not cmd:
                    break
                cmds = cmd.split()
                if len(cmds) == 2 and hasattr(self, cmds[0]):
                    self.sock.send(cmd.encode())
                    func = getattr(self, cmds[0])
                    func(cmds[1])
            self.sock.close()
    
    
    client = Client()
    if __name__ == "__main__":
        client.run()
    View Code

    11、基于udp协议编写程序,实现功能

      1)执行指定的命令,让客户端可以查看服务端的时间

      2)执行指定的命令,让客户端可以与服务的的时间同步

    # 服务端
    import socket
    import time
    import subprocess
    server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    server.bind(("127.0.0.1", 8080))  # 绑定IP、端口
    while True:
        cmd,addr = server.recvfrom(1024)
        if not addr:
            break
        print(cmd.decode(), addr)
        if cmd.decode() == "time":  # 返回服务端时间
            time_now = time.strftime("%Y-%m-%d  %H:%M:%S", time.localtime())  # 当前日期时间
            server.sendto(time_now.encode("gbk"), addr)  # 发送
        else:  # 解析命令
            obj = subprocess.Popen(cmd.decode(), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            server.sendto(stdout+stderr, addr)
    server.close()
    
    
    # 客户端
    import socket
    client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    addr = ("127.0.0.1", 8080)
    
    while True:
        cmd = input(">>>").strip()
        if not cmd:
            break
        client.sendto(cmd.encode(), addr)  # 发送命令
        msg, addr_server = client.recvfrom(1024)  # 接收消息
        print(msg.decode("gbk"))
    client.close()
    View Code

     

     

  • 相关阅读:
    django入门系列 -表单视图
    django学习 -模型层初体验
    python 元组与list的区别
    解决容器内部无法访问宿主机端口的问题
    记一次pyccharm Terminal django 执行 python migrate 无法生成新的数据表的报错过程
    ES学习之ES语法入门
    docker seleniumgrid 问题解决
    selenium的Grid方式遇到 1 requests waiting for a slot to be free. 问题
    js写的ajax
    ajax jQ写的上传进度条
  • 原文地址:https://www.cnblogs.com/yanlin-10/p/9129764.html
Copyright © 2011-2022 走看看