zoukankan      html  css  js  c++  java
  • 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()
     
     
     





  • 相关阅读:
    托付和事件的使用
    在使用supervisord 管理tomcat时遇到的小问题
    无法安装vmware tools的解决方PLEASE WAIT! VMware Tools is currently being installed on your system. Dependin
    (转)Openlayers 2.X加载高德地图
    (转)openlayers实现在线编辑
    (转) Arcgis for js加载百度地图
    (转)Arcgis for js加载天地图
    (转) 基于Arcgis for Js的web GIS数据在线采集简介
    (转) Arcgis for js之WKT和GEOMETRY的相互转换
    (转)Arcgis for Js之Graphiclayer扩展详解
  • 原文地址:https://www.cnblogs.com/pangguoping/p/5675715.html
Copyright © 2011-2022 走看看