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)
      
  • 相关阅读:
    VIM 用正则表达式,非贪婪匹配,匹配竖杠,竖线, 匹配中文,中文正则,倒数第二列, 匹配任意一个字符 :
    中国科学院图书馆分类法
    让进程在后台可靠运行的几种方法 nohup,setsid,&,disown,CTRL-z ,screen
    Exception Handling Statements (C# Reference)
    ChannelFactory.Endpoint 上的地址属性为空。ChannelFactory 的终结点必须指定一个有效的地址。
    .NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱
    WCF Host中的BaseAddress 和 Endpoint中的Address的区别
    使用vs自带的wcf配置工具
    Automatic Code Generation-->Implement Interface
    Learning WCF Chapter1 Exposing Multiple Service Endpoints
  • 原文地址:https://www.cnblogs.com/lotuslaw/p/14015168.html
Copyright © 2011-2022 走看看