zoukankan      html  css  js  c++  java
  • Python socket 套接字实现通信

    首先:我们介绍一下socket什么是socket:
    1. socket 在操作系统中它是处于应用层与传输层的抽象层,它是一组操作起来非常简单的接口(接收数据的),此接口接受数据之后交个操作系统
    那么为什么?直接给操作系统不是更方便吗?那么你就想错了

    因为操作系统的接口远比我们想象的要丑陋复杂,使用操作系统交换数据,非诚繁琐,,开发者们只能想办法让一个中间人和他们打交道,来简单的实现数据交换,那么就是socket套接字.它的作用就是:与操作系统之间数据交换将这些繁琐的操作,进行高度化封装,和简化,
    2.我们能够用它实现简单的通信
    在Python中有一个简单的内置socket 模块我们可以用它实现简单的基于TCP协议的通信

        #基于切换连接的循环通信
        import socket #首先我们在文件中导入socket 模块
        phone = socket.socket() #实例化一个对象
        phone.bind(('127.0.01',8765))#bind是存放ip地址的(这里存放的是本地的IP地址)
        phone.listen(5)#可以设置连接的个数,
        while 1:#循环等待连接
            conn,adds = phone.accept()
            while 1:#要循环聊天我们要重复接收发送
                try: #异常处理
                	receives_commands = conn.recv(1024) #接收命令请求,最多接收1024字节当然你也可以调整
                    receivse_commands = receives_commands.decode('utf-8')#网络传输是以字节的形势的所以我们要进行解码
                    print(f'来自客户端的消息{receives_commands}')  #打印消息
                    if receives_commands.upper(0 == 'Q':break  #正常结束
                    dispatch_orders = inport('请输入:').strip().encode('utf-8')
        			conn.send(dispatch_orders)
               except ConnectionResetError:#客户端异常结束
               		print('客户端终端')
                    break
           conn.close() #关闭连接
        phone.close#关闭服务端
        #客户端
        import socket
        phone = socket.socket()
        phone.connect(('127.0.01',8765))        #连接服务端地址            
     while 1:                  
            dispatch_orders = inport('请输入:').strip().encode('utf-8')#发送请求
            if not dispatch_orders:print('不能为空')#不能为空
            phone.send(dispatch_orders)      #发送                        
            if dispatch_orders.upper() ==b'Q':#正常退出
                break
            receives_commands = phone.recv(1024)#接收服务端的回执
            receives_commands = receives_commands.decode('utf-8')#解码
            print(f'来自客户端的消息{receives_commands}')   #打印                                
        phone.close()#关闭客户端
                                               
    

    那么我们就通过socket实现了一个简单的通信链接循环
    其中我们需要注意的是:
    1.阻塞 accept 和recv 当服务器和客户端都属于同种类阻塞时,那么谁都是同步接受或同步发送的状态那么是处于静止的,这样是不合理的(就是bug)
    2.当我们设计时我们需要知道发送不能为空,不然服务端是接收不到消息的所以我们设置一个判断
    有时我们会发现当我们接受的超过1024字节会发生什么?
    那么下面我们就来将回答下这个问题:
    下面我们引入一个操作系统的模块
    Python中 subprocess 模块就是用来和cmd 命令行进行交流的模块

     obj = subprocess.Popen('dir',#实例化对象括号内第一个参数就是我们的cmd命令行的命令,这里我们写的是dir显示文件夹中内容
                                       shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
    
                                       )
    
                print(obj.stdout.read().decode('gbk'))  # 正确命令
                print(obj.stderr.read().decode('gbk'))  # 错误命令
    

    那么我们在这个基础上建立一个服务端响应客户端命令的机制

    import socket
    import subprocess
    phone = socket.socket()
    phone.bind(('127.0.01',8695))
    phone.listen(5)
    while 1:
        conn,adds = phone.accept()
        while 1:
            try:
                receives_commands = conn.recv(1024)
                if receiver_commands ==b'Q':break 
                #obj = subprocess.Popen(Receiving_instructiors,
                                      # shell= True,
                              #stdout = subprocess.PIPE,
                              #stderr = subprocess.PIPE
    
                                       )
        	obj = subprocess.Popen(receives_commands.decode('utf-8')#动态的传入命令
                              shell = True
                              stdout = subprocess.PIPE
                              stderr = subprocess.PIPE 
                              )
      # print(obj.stdout.read().decode('gbk'))  # 正确命令
      # print(obj.stderr.read().decode('gbk'))  # 错误命令
        	ret = obj.stodut.read()+obj.stderr.read()#将产生的内容进行拼接
        	conn.send(ret)
        except ConnectionResetError:
           		print('客户端终端')
                break    
        conn.close()
    phone.close()
    
    import socket
    
    phone = socket.socket()
    
    phone.connect(('127.0.01',8695))
    while 1:
        dispatch_orders = inport('请输入命令:').strip().encode('utf-8')
        if not dispatch_orders:print('输入不能为空')
        phone.send(dispatch_orders)
        if dispatch_orders.upper() ==b'Q':break
        receives_commands = phone.recv(1024)
        receives_commands = receives_commands.decode('utf-8')
        print(f'来自客户端的消息{receives_commands}')
    phone.close()     
    
    

    那么我们就会发现一个问题,当我们输入的help命令的时候超过了1024字节那么怎么办
    还发现一个问题那就是当我们输入的下个命令时,还是出来help命令的未传输完成的那部分那么就是这就是粘包了
    那么是什么造成的呢?
    怎样解决呢?
    下个博客讲解

  • 相关阅读:
    笔试的坑 onsubmit事件
    正则之
    笔试:找出一个字符串中字符出现最多的次数和该字符
    createDocumentFragment和insertAdjacentHTML
    css权威指南学习笔记--第七章
    使用gulp-minify-css的坑
    arguments[0]() 笔试题的坑
    快速搭建本地服务器
    voxel折腾指南
    力扣第72题 编辑距离
  • 原文地址:https://www.cnblogs.com/wuzifan/p/11410805.html
Copyright © 2011-2022 走看看