Loading

16-网络通信

网络编程

  • 同一个网络中不同的机器之间的通信,涉及到网络编程,有两方,一方叫做客户端(client),一方叫做服务器(server)(B/S,C/S)
  • IP地址
    • 互联网协议地址【Internet Protocol Address】,是联网设备和互联网之间的唯一标识,在同一个网段中,ip地址是唯一的
    • IP地址是一个32位的数字,255.255.255.255 # 被分割为4个八位二进制数,255转换为二进制11111111,八位
      • IPV4:分为四段
      • IPV6:分为六段
  • 端口
    • 数据的发送和接收都需要通过端口,端口号用于唯一标识通信实体上进行网络通信的程序
    • 同一台机器上的不同的应用程序不能占用同一个端口,端口的范围:0~65535
    • 常用端口
      • mysql: 3306
      • oracle:1521
      • tomcat:8080
      • qq:4000
      • 0-1024端口号不能用,常用的服务占用了
  • 网络协议
    • http: 被动式协议
    • tcp
    • udp
    • tcp/ip:互联网协议,协议簇
  • 网络编程核心
    • ip地址+端口号
    • 根据ip地址找到计算机,然后根据端口号找到进程
    • socket
      • socket:实现网络编程的方式, 套接字

tcp

  • 特点

    • 面向连接、可靠(超时重发)、慢
    • tcp是长连接,可以让客户端和服务器端一直连接着,TCP常用于即时通信IM,如:QQ,微信,游戏
    • 类似于生活中的打电话
  • 上网:http使用的tcp连接

  • tcp连接过程

    • 3次握手
  • tcp断开过程

    • 4次挥手
  • tcp通讯

    • 服务器Server

      • 导入socket,创建socket对象,绑定(bind)IP地址和端口,设置监听数,等待客户端连接(accept),连接成功后进行收发(recv,send)数据,关闭连接

      • # TCP通讯 服务端
        import socket
        
        # 1.创建一个socket对象(服务端)
        # AF_INIT: IPV4
        # AF_INET6:IPV6
        # SOCK_STREAM:表示TCP
        # SOCK_DGRAM:表示UDP协议
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
        # 2.绑定IP和PORT(端口)
        server_socket.bind(('127.0.0.1', 8888))
        
        # 3.设置监听数(客户端连接数)
        server_socket.listen(5)
        
        # 4.等待客户端来连接我
        print('服务器已启动,等待客户端连接……')
        client, addr = server_socket.accept()  # 会让程序暂停
        # (<socket.socket fd=480, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.36.139.18', 8888), raddr=('10.36.139.18', 54708)>, ('10.36.139.18', 54708))
        # print(client)
        # print(addr)
        print('有客户端连接成功了')
        
        # 5.连接成功后,就可以开始收发数据了
        while True:
            # 接收数据,阻塞程序(让程序暂停)
            data = client.recv(1024)
            print('客户端说:', data.decode())
            # 发送数据给客户端
            data2 = input('输入发送给客户端的数据')
            client.send(data2.encode())
            # client.send('今晚吃鸡吗'.encode())
        
        
        # 6.关闭连接
        # server_socket.close()
        
      • # 多个客户端同时通信-多线程版
        # 服务器
        from threading import Thread
        import socket
        
        def message(sock):
            while True:
                recv_data = sock.recv(1024)
                if not recv_data:
                    break
                print(recv_data.decode())
                data = 'hello %s' % recv_data.decode()
                sock.send(data.encode())
            sock.close()
        
        server = socket.socket()
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind(('127.0.0.1', 8888))
        server.listen(5)
        while True:
            sock, address = server.accept()
            t = Thread(target=message, args=(sock, ))
            t.start()
        
      • # 多个客户端同时通信-协程版
        # 服务端
        
        from gevent import monkey
        monkey.patch_all()
        
        import gevent
        import socket
        
        def message(sock):
            while True:
                recv_data = sock.recv(1024)
                if not recv_data:
                    break
                print(recv_data.decode())
                data = 'hello %s' % recv_data.decode()
                sock.send(data.encode())
            sock.close()
        
        server = socket.socket()
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind(('127.0.0.1', 8888))
        server.listen(5)
        
        while True:
            sock, address = server.accept()
            g = gevent.spawn(message, sock)
            g.start()
        
      • # 单进程单线程非阻塞版
        import socket
        import time
        
        server = socket.socket()
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind(('127.0.0.1', 8888))
        server.listen(5)
        server.setblocking(False)
        
        sock_list = []
        while True:
            try:
                sock, address = server.accept()
                # print('已链接')
            except:
                pass
                # print('没有链接')
                # time.sleep(1)
            else:
                sock_list.append(sock)
        
            for sock in sock_list:
                try:
                    recv_data = sock.recv(1024)
                    print(recv_data)
                except:
                    pass
                    # print('没有数据')
                else:
                    if not recv_data:
                        sock.close()
                        sock_list.remove(sock)
                    else:
                        send_data = 'hello %s' % recv_data.decode()
                        sock.send(send_data.encode())
        
    • 客户端Client

      • 导入socket,创建socket对象,主动连接服务器端(connect),收发数据

      • # TCP通讯 客户端
        
        import socket
        # 1.创建socket对象(客户端)
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
        # 2.主动连接服务器端
        client_socket.connect(('127.0.0.1', 8888))
        
        # 3.发送或接收服务器数据
        while True:
            # 发送给服务器
            data = input('输入发送给给服务器的数据:')
            client_socket.send(data.encode())
            # 接收服务器数据
            data2 = client_socket.recv(1024)
            print('服务器:', data2.decode())
        

udp

  • 特点

    • 不安全的,无连接,效率高速度快,对数据的大小是有限制的,每个被传输的数据包的大小不超过64k
    • 类似于生活中的写信
  • udp通讯

    • 服务器Server

      • 导入socket包,创建socket对象,绑定IP和端口,收发(recvfrom,sendto)数据

      • # UDP 通讯 服务端
        
        import socket
        # 1.创建UDP的socket对象
        # SOCK_DGRAM:表示UDP
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # 2.绑定IP和port
        server_socket.bind(('10.36.139.18', 6666))
        
        # 3.收发数据
        while True:
            # 接收数据,会阻塞程序
            data, addr = server_socket.recvfrom(1024)
            print(f'客户端{addr}说:', data.decode())
        
            # 发送
            server_socket.sendto('今晚吃鸡'.encode(), addr)
        
    • 客户端Client

      • 导入socket包,创建socket对象,收发数据

      • # UDP 通讯 客户端
        
        import socket
        
        # 1.创建UDP的socket对象
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # 2.收发数据
        while True:
            # 发送数据
            data = input('客户端说:')
            client_socket.sendto(data.encode(), ('10.36.139.197', 5677))
        
            # 接收数据
            data2, addr = client_socket.recvfrom(1024)
            print('服务器说:', data2.decode())
        
    • 模拟飞秋

      • import socket
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        # 发送飞秋消息
        # 1:表示版本
        # 1:自定义的一个包名
        # 王宝强:用户名
        # baoqiang:主机名
        # 32:表示发送数据
        # 'hello你中毒了':发送的内容
        msg = '1:1:宝强:baoqiang:32:hello你中毒了'
        
        client_socket.sendto(msg.encode('gbk'), ('10.36.139.18', 2425))
        

发送邮件

  • import smtplib

  • from email.mime.text import MIMEText

  • 服务器IP及端口

  • 收发对象及授权码

    • # 163邮箱
      import smtplib
      from email.mime.text import MIMEText
      
      # 邮件
      # 163的邮箱服务器:smtp.163.com
      # smtp端口:25
      # 邮箱账号niejeff@163.com
      # 授权码:123456abcde
      
      smtp_server = 'smtp.163.com'
      smtp_port = 25
      
      from_email = 'niejeff@163.com'
      email_code = '123456abcde'  # 这里不是邮箱的密码,而是授权码
      to_email = ['593825767@qq.com']  # 可以写多个
      
      # 创建邮件
      msg = MIMEText('今晚来我家吃鸡')  # 邮件内容
      msg['Subject'] = '大吉大利'  # 标题
      msg['From'] = from_email
      msg['To'] = '593825767@qq.com'  # 不能是列表
      
      # 创建邮箱对象,来发送邮件
      smtp = smtplib.SMTP(smtp_server, smtp_port)  # 连接163邮箱服务器
      smtp.login(from_email, email_code)  # 登陆163邮箱
      smtp.sendmail(from_email, to_email, msg.as_string())
      
      # 关闭
      smtp.close()
      
    • # QQ邮箱
      import smtplib
      from email.mime.text import MIMEText
      
      smtp_server = 'smtp.qq.com'
      smtp_port = 587
      
      from_email = '593825@qq.com'
      email_code = 'xnsihfyjhktnbdba'
      to_email = '593825@qq.com'
      
      # 创建邮件
      msg = MIMEText('学会了吗?')
      msg['Subject'] = 'Python邮件'
      msg['From'] = from_email
      msg['To'] = to_email
      
      # 创建邮箱对象,发送邮件
      smtp = smtplib.SMTP(smtp_server, smtp_port)  # 连接QQ邮箱
      smtp.login(from_email, email_code)  # 登陆qq邮箱
      smtp.sendmail(from_email, to_email, msg.as_string())  # 发送邮件
      
      smtp.close()
      

发送短信

  • # 云之讯
    import requests
    import random
    def send_sms(phone, vcode):
        '''
        :param phone: 手机号
        :param vcode: 验证码
        '''
        # 发送短信
        # 云之讯的短信接口
        url = 'https://open.ucpaas.com/ol/sms/sendsms'
    
        data = {
         "sid":"d84885ebbb2474f9a036346653dab29c",
         "token":"657e97e7906839b34acd71a70f86e938",
         "appid":"786ea1a774054eaeb1201c3a744b92ba",
         "templateid":"556407",
         "param":vcode,
         "mobile":phone,
        }
    
        res = requests.post(url, json=data)
        return res.text
    
    def generate_vcode():
        '''
        生成随机6位验证码
        '''
        vcode = ''
        for _ in range(6):
            vcode += str(random.randint(0, 9))
        return vcode
    
    
    if __name__ == '__main__':
        vcode = generate_vcode()
        print('vcode:', vcode)
        res = send_sms('18840864123', vcode)
        print(res)
    
posted @ 2020-11-21 12:02  lotuslaw  阅读(153)  评论(0编辑  收藏  举报