• python


    1.使用生活中的接打电话,解释socket通信流程

     2.根据上图,写出socket通信的伪代码
    2.1.server端伪代码
    #买手机
     
    #买手机卡
    #开机
    #等待电话
    #收消息
    #发消息
    #挂电话
    2.2.client端伪代码
    #买手机
    #拨号
    #发消息
    #收消息
    #挂电话
     
    3.根据伪代码写出程序
    server端收到client 发送的字母后,把字母转换成大写并发送给client端
    3.1.server端代码
    import socket
    ip_port=('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #买手机卡
    s.bind(ip_port)
    #开机
    s.listen(5)
    #等待电话
    conn,addr = s.accept()
    #conn 相当于一条通信线路
    #收消息
    recv_data = conn.recv(1024)
    #发消息
    send_data = recv_data.upper()
    conn.send(send_data)
    #挂电话
    conn.close()
     
    3.2.client端代码
    import socket
    ip_port = ('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #拨号
    s.connect(ip_port)
    #发送消息
    send_data = input(">>>:").strip()
    s.send(bytes(send_data,encoding='utf-8'))
    #收消息
    recv_data = s.recv(1024)
    print(str(recv_data,encoding='utf-8'))
    #挂电话
    s.close()
     
    运行:
    先运行server端程序,然后运行client端程序
    out:
    >>>:hello
    HELLO
     
    注意点:
    1.server和client 通信传输的是bytes流,在2.7以前是str流
     
    二、socket简单交互
    1.基于python3.5.2版本的socket只能收发字节(python2.7可以发送str)
    2.退出只在客户端退出就OK了
    3.s.accept()和s.recv()是阻塞的,前提是已经建立了连接
     
    server端:
    #循环输入,exit退出,可以输入空字符
    import socket
    ip_port=('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #买手机卡
    s.bind(ip_port)
    #开机
    s.listen(5)
    #等待电话
    conn,addr = s.accept()
    #conn 相当于一条通信线路
    #收消息
    while True:
    recv_data = conn.recv(1024)
    if len(recv_data) == 0:break
    #发消息
    send_data = recv_data.upper()
    conn.send(send_data)

    #挂电话
    conn.close()



    client端
    #循环输入,exit退出,可以输入空字符
    import socket
    ip_port = ('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #拨号
    s.connect(ip_port)
    #发送消息
    while True:
    send_data = input(">>>:").strip()
    if send_data == 'exit': break # 输入exit 退出程序
    if len(send_data) == 0: continue #如果输入是空字符,退出本次循环,继续下次循环
    s.send(bytes(send_data,encoding='utf-8'))

    #收消息
    recv_data = s.recv(1024)
    print("----------------",type(recv_data))
    print(str(recv_data,encoding='utf-8'))
    #挂电话
    s.close()
     
     

    三、

    一个客户端断开连接后,服务端还可以接受新的连接
     
    server端
    #一个客户端断开连接后,服务端还可以接受新的连接
    import socket
    ip_port=('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #买手机卡
    s.bind(ip_port)
    #开机
    s.listen(5)
    #等待电话
    while True:
    conn,addr = s.accept()
    #conn 相当于一条通信线路
    #收消息
    while True:
    try: #客户端强制断开(不是输入exit) 会出现异常。
    recv_data = conn.recv(1024)
    if len(recv_data) == 0:break
    #发消息
    send_data = recv_data.upper()
    conn.send(send_data)
    except Exception:
    break
    #挂电话
    conn.close()

    client端
    #一个客户端断开连接后,服务端还可以接受新的连接
    import socket
    ip_port = ('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #拨号

    s.connect(ip_port)
    #发送消息
    while True:
    send_data = input(">>>:").strip()
    if send_data == 'exit': break # 输入exit 退出程序
    if len(send_data) == 0: continue #如果输入是空字符,退出本次循环,继续下次循环
    s.send(bytes(send_data,encoding='utf-8'))

    #收消息
    recv_data = s.recv(1024)
    print("----------------",type(recv_data))
    print(str(recv_data,encoding='utf-8'))
    #挂电话
    s.close()
     
    关于s.listen(n) n代表:能挂起的链接数,如果n=1 ,代表可以连接一个,挂起一个,第三个拒绝
    表示可以处理一个请求连接,并且挂起一个请求连接。如果再有连接过来会报错。
    如下是我设置s.listen(2)测试的结果:
     
     
    s.listen(2)表示只能挂起两个请求连接,第3个请求就会报错。
     
    解决粘包的问题:
    1.服务端在发送数据之前,先把发送数据的长度告诉客户端,要发送多少数据,然后客户端根据这个数据的长度循环接收就OK
    传输过程:
    服务端:
        1.send  #数据长度
        4.recv  #收到确认信息,开始下一步发送
        send  #发送数据
        
    客户端 :
        2.recv #获取数据长度
        3.send #发送确认信息
        recv #循环接收
     
    server端代码:
    #解决粘包问题
    send_data = bytes(send_data,encoding='utf-8') #编码成utf-8,字节,并把str转换为字节
    ready_tag = 'Ready|%s' %len(send_data)
    conn.send(bytes(ready_tag,encoding='utf-8'))
    feedback = conn.recv(1024) #收到客户端发送过来的Start
    feedback = str(feedback,encoding='utf-8') #把收到的feedback 转换为str
    if feedback.startswith('Start'):
    conn.send(send_data)
     
    client端代码:
    #解决粘包的问题
    ready_tag = s.recv(1024) # Ready|9999
    ready_tag = str(ready_tag,encoding='utf-8')
    if ready_tag.startswith('Ready'): # Ready|9999
    msg_size = int(ready_tag.split('|')[-1])
    start_tag = 'Start'
    s.send(bytes(start_tag,encoding='utf-8')) #给server发送Start,告诉server可以准备发送数据了
    recv_size = 0 #初始化数据大小
    recv_msg =b''

    while recv_size < msg_size:
    recv_data = s.recv(1024)
    recv_msg += recv_data
    recv_size += len(recv_data)
    print('MSG SIZE %s RECE SIZE %s' % (msg_size, recv_size))

    print(str(recv_msg,encoding='utf-8'))
     

    四、socket简单ssh

    server端:
    #一个客户端断开连接后,服务端还可以接受新的连接
    import socket
    import subprocess
    ip_port=('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #买手机卡
    s.bind(ip_port)
    #开机
    s.listen(2)
    #等待电话
    while True:
    conn,addr = s.accept()
    #conn 相当于一条通信线路
    #收消息
    while True:
    try: #客户端强制断开(不是输入exit) 会出现异常。
    recv_data = conn.recv(1024)
    if len(recv_data) == 0:break
    #发消息
    p=subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdout=subprocess.PIPE)
    res = p.stdout.read()
    if len(res) == 0: #处理输入的错误命令
    send_data = 'cmd err'
    else:
    send_data = str(res,encoding='gbk') #windows平台下解码成gbk,并且gbk转换为str
    #解决粘包问题
    send_data = bytes(send_data,encoding='utf-8') #编码成utf-8,字节,并把str转换为字节
    ready_tag = 'Ready|%s' %len(send_data)
    conn.send(bytes(ready_tag,encoding='utf-8'))
    feedback = conn.recv(1024) #收到客户端发送过来的Start
    feedback = str(feedback,encoding='utf-8') #把收到的feedback 转换为str
    if feedback.startswith('Start'):
    conn.send(send_data)
    except Exception:
    break
    #挂电话
    conn.close()
     
    client端:
    #一个客户端断开连接后,服务端还可以接受新的连接
    import socket
    ip_port = ('127.0.0.1',9999)
    #买手机
    s = socket.socket()
    #拨号

    s.connect(ip_port)
    #发送消息
    while True:
    send_data = input(">>>:").strip()
    if send_data == 'exit': break # 输入exit 退出程序
    if len(send_data) == 0: continue #如果输入是空字符,退出本次循环,继续下次循环
    s.send(bytes(send_data,encoding='utf-8'))

    #收消息
    #解决粘包的问题
    ready_tag = s.recv(1024) # Ready|9999
    ready_tag = str(ready_tag,encoding='utf-8')
    if ready_tag.startswith('Ready'): # Ready|9999
    msg_size = int(ready_tag.split('|')[-1])
    start_tag = 'Start'
    s.send(bytes(start_tag,encoding='utf-8')) #给server发送Start,告诉server可以准备发送数据了
    recv_size = 0 #初始化数据大小
    recv_msg =b''

    while recv_size < msg_size:
    recv_data = s.recv(1024)
    recv_msg += recv_data
    recv_size += len(recv_data)
    print('MSG SIZE %s RECE SIZE %s' % (msg_size, recv_size))

    print(str(recv_msg,encoding='utf-8'))
    #挂电话
    s.close()
     
     
     





  • 相关阅读:
    2020牛客暑期多校训练营(第三场)
    2020牛客暑期多校训练营(第二场)
    C# 获取枚举类型中所有描述信息 Xinner
    XPath Xinner
    02kubeadm安装
    thinkphp6:访问redis6(thinkphp 6.0.9/php 8.0.14)
    npm8.3.0 安装@vue/cli 4.5.15
    linux(ubuntu 21.10): php8.0.14:安装phpredis以访问redis(phpredis5.3.5)
    linux(ubuntu21.10):apt方式安装redis6.0.15
    阿里云何万青:南坡VS北坡,阿里云高性能计算行业实践
  • 原文地址:https://www.cnblogs.com/pangguoping/p/5675715.html
Copyright © 2020-2023  润新知