zoukankan      html  css  js  c++  java
  • 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)
      
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/lotuslaw/p/14015168.html
Copyright © 2011-2022 走看看