网络编程

面向对象的使用

#使用面向对象解决datetime.tody()无法序列化的问题import jsonfrom datetime import datetime,date# print(date.today())         #年月日 2020-12-08# print(datetime.today())     #年月日时分秒 2020-12-08 16:07:34.919540class Myjson (json.JSONEncoder):    def default(self, o):        if isinstance(o,datetime):            return o.strftime('%Y-%m-%d %X')        elif isinstance(o,date):            return o.strftime('%Y-%m-%d')        else:            return super().default(self,o)res = {'c1':datetime.today(),'c2':date.today()}print(json.dumps(res,cls=Myjson))

网络编程之 TCP

#学习网络编程可以开发一个cs架构的软件#学习并发、数据库、前端、django可以开发bs架构的软件#软件开发架构C/S架构(client/server)    C:客户端,APP        S:服务端,架构    B/S架构(browser/server)    B:浏览器,taobao.com/jd.com        S:服务端    bs架构实际上也是cs架构    统一接口:比如微信、支付宝        #服务端    24小时不间断提供服务    #客户端    什么时候想体验服务,什么时候去找心仪的服务端寻求服务        #网络编程发展史任何先进的技术基本上都是来源于军事    #回到过去    1.早期的电话电话线        2.大屁股电脑网线        3.笔记本电脑,无线电话 网卡        #要想实现远程通信,第一个需要具备的条件是:物理连接介质人想要实现交流必须统一语言 >>> 英文        计算机想要与计算机远程通信,除了有物理连接介质之外,还需要有一套公共的标准和协议            #OSI协议    OSI七层协议        应用层             HTTP协议:超文本传输协议                HTTPS协议                FTP协议            表示层            会话层            传输层            TCP协议/UDP协议,都是基于端口工作的协议                TCP:流式协议、可靠协议(反馈机制),慢,打电话                        基于TCP协议通信,必须先建立双向通道:TCP协议的三次握手、四次挥手                            三次握手:                                洪水攻击,一台服务器在短时间内接收到了大量的请求                            四次挥手:                                time_wait                UDP:数据报协议,不可靠的协议,快,发短信,QQ                无序建立双向通道,数据的传输不安全                端口:用来唯一标识计算机上的某个应用程序(0~65535),统常0~1024这些都是操作系统默认使用的端口号,建议手动指定8000以后的端口号(访问端口,输出端口)                mysql3306                    redis6379                    djando8000                    flask5000                    tomcat8080                IP 端口:唯一标识接入互联网的一台计算机上的某个应用程序                域名解析:URL DNS            网络层            IP协议,规定了只要是接入互联网的计算机都必须有一个IP地址(公网、私网)                IP地址的特点:点分十进制(0.0.0.0 255.255.255.255)                IP地址目前有两个版本:IPV4、IPV6                路由器:实现局域网与局域网之间的互连                交换机:功能强大的路由器,让连接了交换机的计算机,实现彼此之间的互连                局域网:是构成互联网的基本单位            数据链路层            1.规定电信号的分组方式                2.规定了任何一台接入互联网的计算机,都必须有一块网卡,该网卡上有世界上独一无二的编号(mac地址),该编号由12位16进制数组成(前六位是厂商编号,后六位是流水线编号)                #1、2统称为以太网协议(通信基本靠吼)(局域网内使用)                1.广播风暴(广播、单播)                #ARP协议:根据ip地址,获取Mac地址,本地缓存            物理连接层             基于电信号,传输0100010001这样的二进制数据                OSI五层协议        应用层            传输层            网络层            数据链路层            物理连接层            #应用程序所需要的的数据,都是跟程序所在的那台计算机的内存去要#TCP协议之所以可靠的原因在于反馈机制反馈机制:计算机每次发数据的时候,必须等到对方的才会将内存中的数据清除,否则会在一定的时间内,每隔一段时间发送一次

socket(套接字)

Ji

#serverimport socketserver = socket.socket()            #不传参数,默认使用的就是TCP协议,买手机server.bind(('127.0.0.1',8080))      #bind内为元组,127.0.0.1,为本地回环地址,插电话卡server.listen(5)                    #半连接池,开机conn,addr = server.accept()         #接听电话,一直等待(阻塞)data = conn.recv(1024)              #听别人说话,接收1024个字节,阻塞print(data)conn.send(b'hello baby')            #给别人回话conn.close()                        #挂电话server.close()                      #关机#clientimport socketclient = socket.socket()                    #拿电话client.connect(('127.0.0.1',8080))          #拨号,写对方的ip和端口client.send(b'hello world')                 #对别人说话data = client.recv(1024)                    #听别人说话,阻塞print(data)client.close()                              #挂电话#send()与recv()不要出现两边相同的情况#recv()是跟内存要数据,至于数据的来源,recv不管

循环通信

#serverimport socketserver = socket.socket()            #生成一个对象server.bind(('127.0.0.1',8080))      #绑定ip和端口server.listen(5)                    #半连接池conn,addr = server.accept()         #阻塞while True:    data = conn.recv(1024)              #听别人说话,接收1024个字节    print(data)    conn.send(data.upper())            #给别人回话# conn.close()                        #挂电话# server.close()                      #关机#clientimport socketclient = socket.socket()                    #生成一个对象client.connect(('127.0.0.1',8080))while True:    msg = input('请输入要发送的内容>>>: ').encode('utf-8')    client.send(msg)                            #对别人说话    data = client.recv(1024)                    #听别人说话    print(data)# client.close()

socket通信的一些问题

#serverimport socketserver = socket.socket()            #生成一个对象server.bind(('127.0.0.1',8080))      #绑定ip和端口server.listen(5)                    #半连接池conn,addr = server.accept()         #阻塞,addr就是客户端的地址while True:    try:        data = conn.recv(1024)              #conn()类似于双向通道        print(data)                         #Mac和linux客户端异常退出之后,服务端不会报错,会一致接收b''        if len(data) == 0:break        conn.send(data.upper())            #给别人回话    except ConnectionResetError as e:        print(e)        breakconn.close()                        #挂电话server.close()                      #关机#clientimport socketclient = socket.socket()                    #生成一个对象client.connect(('127.0.0.1',8080))while True:    msg = input('请输入要发送的内容>>>: ').encode('utf-8')    if len(msg) == 0:continue               #解决客户端输入空,resc()同时出现的情况    client.send(msg)                            #对别人说话    data = client.recv(1024)                    #听别人说话    print(data)# client.close()

连接循环

#服务端固定的ip和端口    24小时不间断提供服务    #serverimport socketserver = socket.socket()            #生成一个对象server.bind(('127.0.0.1',8080))      #绑定ip和端口server.listen(5)                    #半连接池,允许最大的等待数(连接数为6)while True:    conn,addr = server.accept()         #阻塞,addr就是客户端的地址    while True:        try:            data = conn.recv(1024)              #conn()类似于双向通道            print(data)                         #Mac和linux客户端异常退出之后,服务端不会报错,会一致接收b''            if len(data) == 0:break            conn.send(data.upper())            #给别人回话        except ConnectionResetError as e:            print(e)            break    conn.close()                        #挂电话# server.close()                      #关机#clientimport socketclient = socket.socket()                    #生成一个对象client.connect(('127.0.0.1',8080))while True:    msg = input('请输入要发送的内容>>>: ').encode('utf-8')    if len(msg) == 0:continue               #解决客户端输入空,resc()同时出现的情况    client.send(msg)                            #对别人说话    data = client.recv(1024)                    #听别人说话    print(data)# client.close()

模拟终端

#subprocess模块import subprocesswhile True:    cmd = input('请输入您的命令>>>: ')    obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)    print(obj.stdout.read().decode('gbk'))        #正确命令返回结果,windows默认使用gbk编码    print(obj.stderr.read().decode('gbk'))        #错误命令返回结果

TCP协议的粘包问题

#TCP协议的特点会将数据量比较小的,并且时间间隔比较短的数据一次性打包发给对方#serverimport socketserver = socket.socket()server.bind(('127.0.0.1',8080))server.listen(5)conn,addr = server.accept()data = conn.recv(5)print(data)data = conn.recv(5)print(data)data = conn.recv(4)print(data)conn.send(b'hello baby')conn.close()server.close()#clientimport socketclient = socket.socket()client.connect(('127.0.0.1',8080))client.send(b'hello')client.send(b'world')client.send(b'baby')data = client.recv(8)print(data)client.close() #少的数据量将会一次打包发送给服务端,节省资源#如果知道数据的发送方发送的字节数,那么双方的信息就可以不用在担心'字节长度问题'

struct模块

#struct模块可以将任意字符串打包成字节长度为4的包,解包后仍可以得到原来字符串的长度    当原始数据特别大的时候,i模式装不下了,这个时候就需要更换模式import structstr = 'evfreatteg.t.g..t;hyh;y;5;yjjjjjn'print('原始的: ',len(str))str1 = struct.pack('i',len(str))        #将数据打包print(len(str1))                        #包长度固定位4str2 = struct.unpack('i',str1)[0]       #将数据解包print('解包后的: ',str2)原始的:  334解包后的:  33

使用struct模块解决粘包问题

#解决粘包问题 服务端:    1.先制作一个要发送给客户端的字典        2.制作字典的报头        3.发送字典的报头        4.发送字典        5.再发送真实数据长度    客户端:    1.先接受字典的报头        2.解析拿到字典的数据长度3.接收字典        4.从字典中获取真实数据长度        5.接收真实数据        #serverimport socketimport subprocessimport structimport jsonserver = socket.socket()server.bind(('127.0.0.1',8080))server.listen(5)while True:    conn,addr = server.accept()    while True:        try:            cmd = conn.recv(1024)            if len(cmd) == 0:break            cmd = cmd.decode('utf-8')            obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)            res = obj.stdout.read()   obj.stderr.read()            d = {'name':'syy','file_size':len(res),'info':'大家为我骄傲'}            json_d = json.dumps(d)            #1.先制作一个字典的报头            header = struct.pack('i',len(json_d))            #2.发送字典报头            conn.send(header)            #3.发送字典            conn.send(json_d.encode('utf-8'))            #4.再发送真实数据            conn.send(res)            # conn.send(obj.stdout.read())  #只能read()一次            # conn.send(obj.stderr.read())        except ConnectionResetError as e:            print(e)            break    conn.close()# server.close()                      #关机#clientimport socketimport structimport jsonclient = socket.socket()                    #生成一个对象client.connect(('127.0.0.1',8080))while True:    msg = input('请输入要发送的内容>>>: ').encode('utf-8')    if len(msg) == 0:continue               #解决客户端输入空,resc()同时出现的情况    client.send(msg)                            #对别人说话    #1.先接收字典报头    header_dict = client.recv(4)    #2.解析报头,获取字典长度    dict_size = struct.unpack('i',header_dict)[0]    #3.循环接收字典数据    dict_bytes = client.recv(dict_size)    dict_json = json.loads(dict_bytes.decode('utf-8'))    #4.从字典中获取信息    print(dict_json)    recv_size = 0    real_data = b''    while recv_size < dict_json.get('file_size'):        data = client.recv(1024)        real_data  = data        recv_size  = len(data)    print(real_data.decode('gbk'))# client.close()

练习

#习题写一个上传电影的功能    1.循环打印某一个文件夹下面的所有的文件        2.用户想要上传的文件        3.将用户选择的文件上传到服务器        4.服务端保存该文件        #serverimport socketimport subprocessimport structimport jsonserver = socket.socket()server.bind(('127.0.0.1',8080))server.listen(5)while True:    conn,addr = server.accept()    while True:        try:            header_len = conn.recv(4)            #解析字典报头            header_len = struct.unpack('i',header_len)[0]            #在接收字典数据            header_dic = conn.recv(header_len)            real_dic = json.loads(header_dic.decode('utf-8'))            #获取真实数据长度            total_size = real_dic.get('file_size')            #循环接收并写入文件            recv_size = 0            with open(real_dic.get('file_name'),'wb') as f:                while recv_size < total_size:                    data = conn.recv(1024)                    f.write(data)                    recv_size  = len(data)                print('上传成功')        except ConnectionResetError as e:            print(e)            break    conn.close()# server.close()                      #关机#clientimport socketimport structimport jsonimport osclient = socket.socket()                    #生成一个对象client.connect(('127.0.0.1',8080))while True:    #获取电影列表,循环展示    MOVIE_DIR = r'D:\python视频\day29\视频'    movie_list = os.listdir(MOVIE_DIR)    for i,movie in enumerate(movie_list,1):        print(i,movie)    #用户选择    choise = input('请输入电影序号>>>: ').strip()    #判断是否是数字字符串    if choise.isdigit():        choise = int(choise)        #判断用户输入的值的范围是否有效        if choise in range(1,len(movie_list) 1):            #获取到用户想要上传的文件名            path = movie_list[choise-1]            #拼接文件的绝对路径            file_path = os.path.join(MOVIE_DIR,path)            #获取文件大小            file_size = os.path.getsize(file_path)            #定义一个字典            res_d = {                'file_name':path,                'file_size':file_size,                'msg':'尼桑~'            }            #序列化字典            json_d = json.dumps(res_d)            json_bytes = json_d.encode('utf-8')            #1.制作字典格式报头            header = struct.pack('i',len(json_bytes))            #2.发送字典报头            client.send(header)            #3.再发字典            client.send(json_bytes)            #4.再发文件数据,打开文件循环发送            with open(file_path,'rb') as f:                for line in f:                    client.send(line)    else:        print('请输入数字序号!')

异常处理

#什么是异常程序在运行过程中,出现不可预知的错误    并且该错误没有对应的处理机制,那么就会以异常的形式表现出来    造成的影响是整个程序无法正常运行    #异常的结构1.异常的类型NAMEERROP    2.异常的信息name 'hhhhhhh' is not defined    3.异常的位置File "E:/python_test/a.py", line 6, in <module>    #异常的种类1.语法错误    是程序员可以立刻解决的,这种错误是不能容忍的            2.逻辑错误    这种错误是可以被容忍的,因为一眼看不出来        针对逻辑上的错误,可以采用异常处理机制进行捕获        #常见的错误类型1.名字错误NAMEERROP,变量名、函数名、类名不存在    2.语法错误SyntaxError,if/while    3.键不存在KeyErrord = {'name':'syy'}print(d['password'])4.值错误ValueErrorint('ssss')5.索引错误IndexErrorl = [1,2,3]print(l[111])6.关键字assert断言错误  AssertionError#异常处理在你认为可能会出现bug的代码块上方try一下(try代码块越少越好)    #异常处理的格式try:    想要监控的代码块except 错误类型:    监控到错误类型后自定义的反馈    try:    想要监控的代码块except 错误类型 as e:#e代表本来代码的错误反馈    监控到错误类型后自定义的反馈    try:    想要监控的代码块except 错误类型:    监控到错误类型后自定义的反馈else:    print('被检测的代码没有任何异常发生,才会走else')finally:    print('被检测的代码无论有没有异常发生,都会走finally')    #例try:    nameexcept NameError:    print('NameError已被我处理')        #except可以跟多个try:    # name    # l = [1,2,3]    # l[100]    # d = {'name':'syy'}    # d['password']    # if#语法错误不能被监控    int('www')except NameError:    print('NameError已被我处理')except IndexError:    print('IndexError已被我处理')except KeyError:    print('KeyError已被我处理')except SyntaxError:    print('SyntaxError已被我处理')except ValueError:    print('ValueError已被我处理')        #万能异常捕获try:    # name    # l = [1,2,3]    # l[100]    # d = {'name':'syy'}    # d['password']    # if    int('www')except Exception:#万能异常捕获,继承自BaseException    print('所有异常已被我处理')        #else语法try:    # name    # l = [1,2,3]    # l[100]    # d = {'name':'syy'}    # d['password']    # if    int('1')except Exception:    print('所有异常已被我处理')else:    print('被检测的代码没有任何异常发生,才会走else')finally:    print('被检测的代码无论有没有异常发生,都会走finally')

抛出异常

#关键字raise,就是主动抛出异常if 'syy' == 'cool':    passelse:    raise NameError('我觉得不对...')

断言错误

#关键字assert在关键字assert预言的位置,如果语言对了,代码正常执行,错了的话,报AssertionError错误l = [1,2,3]assert len(l) > 0print('断言对了才会走这行代码')

自定义异常

#主动抛出异常,其实就是将异常类的对象打印出来,会走__str__方法(对象的属性被打印的时候触发)class MyError(BaseException):    def __init__(self,msg):        super().__init__()        self.msg = msg    def __str__(self):        return '<%shhhhhh>' %self.msgraise MyError('自定义异常')

网络编程之 UDP

UDP通信的基本使用

#UDP通信数据包协议自带报头    基于UDP协议的数据传输,数据是不安全的(客户端只发,无论服务端有没有接收)    #serverimport socketserver = socket.socket(type=socket.SOCK_DGRAM)      #UDP协议server.bind(('127.0.0.1',8080))#UDP没有半连接池的概念不需要设置半连接池#因为没有双向通道,所以不需要accept,直接设置通信循环即可while True:    data,addr = server.recvfrom(1024)    print('数据',data)        #客户端发来的消息    print('地址',addr)        #客户端地址    server.sendto(data.upper(),addr)    #clientimport socketclient = socket.socket(type=socket.SOCK_DGRAM)#不需要建立连接,直接进入通讯循环server_address = ('127.0.0.1',8080)while True:    client.sendto(b'hellow',server_address)    data,addr = client.recvfrom(1024)    print('服务端发来的数据',data)    print('服务端的地址',addr)    #UDP类似于发短信,TCP类似于打电话

UDP协议与TCP协议的异同

#TCP协议1.TCP协议客户端允许为空    2.TCP协议存在粘包问题    3.udp协议服务端不存在的情况下,客户端照样会报错    4.TCP协议不支持并发,使用模块可以做到并发    #UDP协议1.udp协议客户端允许为空?是的    2.udp协议不会粘包?会的    3.udp协议服务端不存在的情况下,客户端照样不会报错?会报错,client.recvfrom(1024)报错    4.udp协议支持并发是的    #并发:看起来像是同时运行#并行:真正意义上的同时运行

基于UDP协议实现简易版的QQ

#serverimport socketserver = socket.socket(type=socket.SOCK_DGRAM)      #UDP协议server.bind(('127.0.0.1',8080))while True:    data,addr = server.recvfrom(1024)    print(data.decode('utf-8'))        #客户端发来的消息    msg = input('请输入你要发送的内容>>>: ').strip()    server.sendto(msg.encode('utf-8'),addr)    #clientimport socketclient = socket.socket(type=socket.SOCK_DGRAM)server_address = ('127.0.0.1',8080)while True:    msg = input('请输入您要发送的内容(客户端1)>>>: ').strip()    client.sendto(msg.encode('utf-8'),server_address)    data,addr = client.recvfrom(1024)    print(data.decode('utf-8'))

socketserver模块

模块的简单使用

#serverimport socketserverclass MyServer(socketserver.BaseRequestHandler):    def handle(self):        print('来了?老弟')        #创建一个基于TCP的对象#只要有客户端连接,会自动交给自定义类中的handler方法去处理server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer)#启动该服务的对象server.serve_forever()#clientimport socketclient = socket.socket()client.connect(('127.0.0.1',8080))

socketserver模块使TCP协议支持并发

#serverimport socketserverclass MyServer(socketserver.BaseRequestHandler):    def handle(self):        # print('来了?老弟')        while True:            data = self.request.recv(1024)            print(self.client_address)      #客户端地址            print(data.decode('utf-8'))            self.request.send(data.upper())#村赶紧啊一个基于TCP的对象server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer)#启动该服务的对象server.serve_forever()#clientimport socketclient = socket.socket()client.connect(('127.0.0.1',8080))while True:    client.send(b'hello')    data = client.recv(1024)    print(data.decode('utf-8'))

socketserver模块与UDP协议

#serverimport socketserverclass MyServer(socketserver.BaseRequestHandler):    def handle(self):        # print('来了?老弟')        while True:            data,sock = self.request            print(self.client_address)      #客户端地址            print(data.decode('utf-8'))            sock.sendto(data.upper(),self.client_address)#村赶紧啊一个基于TCP的对象server = socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyServer)#启动该服务的对象server.serve_forever()#clientimport socketimport timeclient = socket.socket(type=socket.SOCK_DGRAM)server_address = ('127.0.0.1',8080)while True:    client.sendto(b'hello',server_address)    data,addr = client.recvfrom(1024)    print(data.decode('utf-8'),addr)    time.sleep(1)

来源:https://www.icode9.com/content-1-782451.html

(0)

相关推荐

  • 第99天:TCP 编程

    网络连接与通信是我们学习任何编程语言都绕不过的知识点.Python 也不例外,本文就介绍因特网的核心协议 TCP ,以及如何用 Python 实现 TCP 的连接与通信. TCP 协议 TCP协议(T ...

  • (2条消息) Python3的socket和socketserver网络编程(聊天和文件传输功能)

    文章目录 前言 一.TCP以及UDP的选择 二.socket以及socketserver 三.使用步骤 1.打开cmd输入python total_sever.py,创建服务器 2.打开cmd输入py ...

  • Python网络编程

    TCP 客户端与服务器之间建立连接需要进行三次握手 客户端--->服务器  服务器--->客户端  客户端--->服务器,这样做的好处是可以保证数据的完整缺点是慢. UDP 是用户数 ...

  • Python网络编程基础及socket之TCP收发消息及文件

    网络编程必须了解的基本概念 MAC地址:是全球唯一标示的网络接口,每一个网卡接口.交换机接口.路由器接口的mac地址均不相同.mac地址是通信子网内部相互通信的标识,交换机根据mac地址区分用户.ma ...

  • 迅为4412开发板Qt网络编程-UDP实现服务器和客户端

    UDP 协议是开放式,无连接,不可靠的传输层通信协议,但它收发数据的速度相对于 TCP 快很多,常用在传输音视频等数据量非常大的场合.udp 网络编程只需要使用一个类 QUdpSocket. 本实验中 ...

  • 老曹眼中的网络编程基础

    我们是幸运的,因为我们拥有网络.网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界. 然而,网络的无标度和小世界特性使得它又是复杂的,无所不在,无所不能,以致于我们无法区分甚至无法描述. ...

  • 4412开发板Qt网络编程-TCP实现服务器和客户端

    网络编程有 TCP 和 UDP,TCP 编程需要用到俩个类:QTcpServer 和 QTcpSocket. 1 TCP 实现服务器和客户端 TCP 协议(Transmission Control P ...

  • 网络编程及前端面试题!Python入门

    当我们学习Python时,需要掌握的的知识有很多,除了有关Python的专业知识外,我们还需要学习网络编程.前端等知识,对此这篇文章为大家总结一下Python常见面试题之网络编程及前端的问题. 第一: ...

  • 【汇总】Python网络编程框架有哪些?

    伴随着人工智能时代的到来,Python这门语言变得非常受欢迎,成为了很多开发人员的热捧,甚至还有不少小白.其他岗位就业人员想要转行学习Python,尤其是想要从事网络编程的人员,那么你知道Python ...

  • day21 网络编程(下)

    版权声明:本博客转载自路飞学城Python全栈开发培训课件,仅用于学习之用,严禁用于商业用途. 欢迎访问路飞学城官网:https://www.luffycity.com/ 课程目标:学会网络编程开发的 ...

  • 03Python网络编程之多线程服务端。

    # 多线程和单线程其实是差不多的,知识我们多开了几个线程# 来让多个客户端连接,这样同一时间可以有四个客户端跟服务端通信 import zen_utils# 导入线程模块from threading ...

  • 03Python网络编程之单线程服务端

    # 对于单线程的服务端,我们借助于zen_utils(我们自己编写好的一些函数)是很容易就实现的.# 导入这个模块import zen_utils if __name__ == '__main__': ...

  • 03Python网络编程之客户端。

    # 这个是客户端,下边我会写几个关于服务的单线程.多线程.异步服务端的脚本. # 定义一个客户端,# 导入接收终端参数.随机数.socket.自己编写工具的模块.import argparse, ra ...

  • 03Python网络编程系列之服务端

    # 这里边是一个定义了服务端的一系列函数,是Python网络编程这本书第七章的第一个例子.# 这是供后边函数进行调用了,然后我们来进行研究网络的单线程编程,多线程编程.异步网络编程等. # 导入网络编 ...