zoukankan      html  css  js  c++  java
  • socket基本语法和粘包

    一。基本语法

    127.0.0.1     是本地回环地址

    客户端                                                                                                                                                                          服务端

    import socket                                                                                                                                                               import socket

    client=socket.socket()                                                                                                                                                  server=socket.socket()         #买手机
    ip_port=('127.0.0.1',8088)                                                                                                                                            ip_port=('127.0.0.1',8088)

    client.connect(ip_port)   #连接的是一个元组,所以提前写好需要输入的IP和port                                                        server.bind(ip_port)             #插电话卡  注意括号内是一个小元组,避免出错,先将Ip_port先写在外面

                                                       server.listen(5)                    #监听状态   5是半连接池

                                                      conn,addr=server.accept()   #建立通信,已完成三次握手

    client.secd(b'hello boy!')                                                   data=conn.recv (1024)        #   和客户端对照者写,move right   必须是一个输入,一个接受,否则就会出现双方都在输入/输出状态,就会出现阻塞现象

                                                                                                     print(data)

    data=client.recv(1024)                                         conn.send(b'hihihihihi')                                       

    print(data)                                              conn.close()

    client.close()    #一次通信结束                                     server.close()

    二。通信循环

    上面我们已经可以实现两个计算机之间的相互通信,但是只是一次通信,如果要多次通信,就得多次输入,我们前面学过的可以多次输入的有什么?while循环

    客户端                                                                                                                                                                          服务端

    import socket                                                                                                                                                               import socket

    client=socket.socket()                                                                                                                                                  server=socket.socket()         #买手机
    ip_port=('127.0.0.1',8088)                                                                                                                                            ip_port=('127.0.0.1',8088)

    client.connect(ip_port)   #连接的是一个元组,所以提前写好需要输入的IP和port                                                        server.bind(ip_port)             #插电话卡  注意括号内是一个小元组,避免出错,先将Ip_port先写在外面

                                                       server.listen(5)                    #监听状态   5是半连接池

                                                      conn,addr=server.accept()   #建立通信,已完成三次握手

    while True:                                             while True:

      client.send(b'hello boy!')                                                     data=conn.recv (1024)   

                                                                                                         print(data)

      data=client.recv(1024)                                           conn.send(b'hihihihihi')                                       

      print(data)                                              

                                                       conn.close()

    client.close()    #一次通信结束                                     server.close()

    三。链接循环

    通信循环也已经实现了两台计算机之间的多次信息交流,但是发现只能一次服务一个客户端,但是服务端的特点是24小时不间断的提供服务,并且是提供给多个用户,地址也是不变的,那么如何实现提供多个服务给用户呢?链接循环走起来!

    客户端                                                                                                                                                                          服务端

    import socket                                                                                                                                                               import socket

    client=socket.socket()                                                                                                                                                  server=socket.socket()         #买手机
    ip_port=('127.0.0.1',8088)                                                                                                                                            ip_port=('127.0.0.1',8088)

    client.connect(ip_port)   #连接的是一个元组,所以提前写好需要输入的IP和port                                                        server.bind(ip_port)             #插电话卡  注意括号内是一个小元组,避免出错,先将Ip_port先写在外面

                                                       server.listen(5)                    #监听状态   5是半连接池

                                                  while True:   #这里就可以实现多个客户服务,所以得将建立连接信息放到第一个while里面     我们发现最多只可以打开6个客户端,一旦超过就报错

                                                       这是因为半连接池是5,就相当于只提供了5个凳子,先服务第一个用户,外面可以由5个人在 等,但是再来一个就报错!

                                                      conn,addr=server.accept()   #建立通信,已完成三次握手

    while True:                                             while True:

      client.send(b'hello boy!')                                                     data=conn.recv (1024)   

                                                                                                         print(data)

      data=client.recv(1024)                                           conn.send(b'hihihihihi')                                       

      print(data)                                              

                                                       conn.close()

    client.close()    #一次通信结束                                     server.close()

    四。异常处理

    实际生活中:

    1,用户提前中断了通道,会发现服务端直接报错,所以要对这个进行异常捕获

    2.网络信号不好导致的问题

    3.tcp协议是流的传输,输入信息不可以是空

    客户端                                                                                                                                                                          服务端

    import socket                                                                                                                                                               import socket

    client=socket.socket()                                                                                                                                                  server=socket.socket()         #买手机
    ip_port=('127.0.0.1',8088)                                                                                                                                            ip_port=('127.0.0.1',8088)

    client.connect(ip_port)   #连接的是一个元组,所以提前写好需要输入的IP和port                                                        server.bind(ip_port)             #插电话卡  注意括号内是一个小元组,避免出错,先将Ip_port先写在外面

                                                       server.listen(5)                    #监听状态   5是半连接池

                                                  while True:  

                                                      conn,addr=server.accept()   #建立通信,已完成三次握手

    while True: 

      msg=input('>>>:').encode('utf-8') 

      if len(msg)==0:continue                                        while True:

                                                         try:

      client.send(msg)                                                          data=conn.recv (1024) 

                                                            if len(data)==0:break   #针对mac 和Linux系统,需要自己再加一步 

                                                                                                           print(data)

      data=client.recv(1024)                                             conn.send(b'hihihihihi')                                       

      print(data)                                               except ConnectionRaseError:break

                                                       conn.close()

    client.close()    #一次通信结束                                     server.close()

    五。粘包问题

    发现当自己输入的是task list之类的东西时,然后再次输入dir但是还是接收的是task list的信息,就是粘包,两个数据粘在了一起,解决方式

    1.将recv的值改大,但是不是根本性的解决方式,因为你不知道用户传入的东西是多大,所以不推荐

    2.将我们要传的东西先打包成固定大小,对方接受以后解包,看到大小,然后再根据大小来接受我们要传的东西(看下面总结)

    总结:

    发送消息端:

    1.先发报头    2.在发字典(序列化成字符串)       3.再发你的真实数据

    接收消息端:

    1.先收4个长度的报头   2.解包拿到字典数据长度    3.接收字典(反序列化)获取字典里面的所有信息         4.接收真实数据

    用到的模块分别是struck(pack,unpack),subprocess(标准输出stdout和错误流stderr)  json(序列化dumps和反序列化loads)   以及socket

    客户端

    import socket
    import json
    import struct
    client=socket.socket()
    ip_port=('127.0.0.1',8099)
    client.connect(ip_port)

    while True:
    msg=input('>>>:').strip().encode('utf-8')
    if len(msg)==0:continue
    client.send(msg)
    head=client.recv(4) #head就是4
    #对这个报头进行解包,获取真实数据的长度
    head_len=struct.unpack('i',head)[0]
    head_dic=json.loads(client.recv(head_len).decode('utf-8')) #反序列化
    print(head_dic)

    total_size=head_dic['len'] #一定要由索引0
    # unpack拿出来的是一个小元组
    print(total_size)

    #如果发送内容过大,怎么做,循环接收值

    recv_size=0
    res=b''
    while recv_size<total_size: #对需要的数据进行循环接受
    data=client.recv(1024)
    res+=data
    recv_size+=len(data) #len(data)真实收到的数据,所以是data,不是1024
    print(res.decode('gbk'))

    服务端:

    #服务端给用户端发送一个字典的内容
    import socket
    import struct
    import json
    import subprocess

    server=socket.socket()

    ip_port=('127.0.0.1',8099)

    server.bind(ip_port)

    server.listen(5)

    while True:

    conn,addr=server.accept()

    while True:
    try:
    data=conn.recv(1024)
    if len(data)==0:break
    print(data)
    order=subprocess.Popen(data.decode('utf-8'),
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
    )

    stdout=order.stdout.read()
    stderr=order.stderr.read()
    #传过来的真实长度
    print(len(stderr+stdout))
    #传字典
    head_dic = {
    'file_name': 'cls.txt',
    'len': len(stdout + stderr)
    }
    #字典序列化
    head_bytes=json.dumps(head_dic).encode('utf-8')

    #制作报头
    head=struct.pack('i',len(head_bytes)) #将需要发送给客户端的打包成4个字节

    conn.send(head) #head=4想拿到一些描述,传个字典

    conn.send(head_bytes)
    conn.send(stderr+stdout)
    except ConnectionResetError:break
  • 相关阅读:
    新建存储过程
    c#List移除列表中的元素
    学习总结初篇:发现问题
    webpack的几个使用方法
    Does Lamda expression return value?
    委托的最佳科普解释
    正则表达式字符匹配攻略
    Beta冲刺 第一天
    ###Beta准备
    高校征信系统项目Postmortem结果
  • 原文地址:https://www.cnblogs.com/mcc61/p/10806709.html
Copyright © 2011-2022 走看看