码迷,mamicode.com
首页 > 其他好文 > 详细

socket套接字

时间:2019-08-08 00:31:09      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:serve   proc   decode   模拟   地址   pip   终端命令   时间   exce   

什么是套接字?

  1. 一组接口
  2. 作用于应用层与传输层之间
  3. 隐藏了传输层下面复杂的TCP/IP协议的实现

基于TCP协议的socket

  1. 流式协议,面向流的通信是无消息保护边界的
  2. 会将数据少、时间间隔短的数据一次性打包发送
  3. 可靠但粘包
    1. 数据不会丢,包没收完,会继续上次继续接收数据
    2. 数据是可靠的
  4. 只有TCP有粘包现象

粘包问题:

产生原因:

  1. 发送的数据小,时间段,TCP会议会自动合成数据,造成粘包。(发送方的缓存机制)
  2. 接收数据只接收一部分,下次接收会继续上次接收数据。(接收方的缓存机制)

只发生在TCP协议。

问题的根源:

? 接收方不知道消息的大小

解决方案:

  1. 发送方提供数据大小
  2. 利用struct模块调用.pack将长度打包header报头发送
  3. 接收方利用struct调用.unpack解包header报头取出长度

案例:利用subprocess模拟终端命令输入

客户端                                     服务端:

1、连接服务                                  1、开启服务                                                          
2、发送命令                                  2、接收客户端命令                                                          
3、接收header报头                            3、利用subprocess返回命令结果res
4、struct.unpack header报头得到字典长度       4、构造res数据的字典
5、利用字典长度接收字典                        5、序列化字典,得出序列化后的字典长度
6、拿出字典里面真实数据长度                    6、利用struct模块构造字典长度的header头
7、分段接收真实数据                           7、发送header头
                                           8、发送字典
                                           9、发送真实数据

client.py:



import socket
import struct
import json


IP = '127.0.0.1'
PORT = 8001

client = socket.socket()
client.connect((IP, PORT))

while True:
    cmd = input('>>>').strip()
    client.send(cmd.encode('utf-8'))
    # 接收字典报头
    data = client.recv(4)
    dict_size = struct.unpack('i', data)[0]
    # 接收字典数据
    dict_data = client.recv(dict_size)
    dic = json.loads(dict_data.decode('utf-8'))
    # 取出数据长度
    file_size = dic.get('file_size')
    #接收真实数据
    recv_size = 0
    real_data = b''
    while recv_size < file_size:
        data = client.recv(1024)
        real_data += data
        recv_size += len(data)

    print(real_data.decode('utf-8'))

server.py

from socket import SOL_SOCKET, SO_REUSEADDR
import socket
import subprocess
import struct
import json

IP = '127.0.0.1'
PORT = 8001

server = socket.socket()
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind((IP, PORT))
server.listen(5)

while True:
    conn, addr = server.accept()
    while True:
        try:
            print('客户端地址:', addr)
            cmd = conn.recv(1024)
            obj = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            res = obj.stdout.read() + obj.stderr.read()

            # 构造一个字典
            dic = {'name': 'jason', 'file_size': len(res), 'info': 'great'}
            dump_dict = json.dumps(dic)

            # 制作字典报头
            header = struct.pack('i', len(dump_dict))
            # 发送字典报头
            conn.send(header)
            # 发送字典
            conn.send(dump_dict.encode('utf-8'))
            # 发送真实数据
            conn.send(res)
        except ConnectionResetError as e:
            break

    conn.close()

socket套接字

标签:serve   proc   decode   模拟   地址   pip   终端命令   时间   exce   

原文地址:https://www.cnblogs.com/KbMan/p/11318630.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!