• 网络编程-套接字(socket)


    一、Socket(套接字)

    ★注意点:

    ① 127.0.0.1本机地址回环:只能识别自己,其他人无法访问

    ② send与recv对应,不要出现两边是相同的情况,recv是跟内存要数据,无需考虑

    ③ tcp特点是会将数据量比较小的并且时间间隔比较短的数据,一次性打包发送给对方

     1 import socket
     2 
     3 server = socket.socket()  # 买手机 不传参数默认用的就是TCP协议
     4 server.bind(('127.0.0.1',8080))  # bind((host,port))  插电话卡  绑定ip和端口
     5 server.listen(5)  # 开机    半连接池
     6 
     7 conn, addr = server.accept()  # 接听电话  等着别人给你打电话    
     8 data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          
     9 conn.send(b'hello baby~')  # 给别人回话
    10 
    11 conn.close()  # 挂电话
    12 server.close()  # 关机
    Server端代码
     1 import socket
     2 
     3 client = socket.socket()  # 拿电话
     4 client.connect(('127.0.0.1',8080))  # 拨号   写的是对方的ip和port
     5 
     6 client.send(b'hello world!')  # 对别人说话
     7 data = client.recv(1024)  # 听别人说话
     8 print(data)
     9 
    10 client.close()  # 挂电话
    Client端代码

    二、TCP粘包问题

      我们基于TCP协议写一个远程命令操控

     1 from socket import *
     2 import subprocess
     3 
     4 1024
     5 
     6 tcp_socket_server=socket(AF_INET,SOCK_STREAM)
     7 tcp_socket_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
     8 tcp_socket_server.bind(('127.0.0.1',8888))
     9 tcp_socket_server.listen(5)
    10 
    11 while True:
    12     conn,addr=tcp_socket_server.accept()
    13 
    14     while True:
    15         cmd=conn.recv(1024)
    16         if len(cmd) == 0:break
    17 
    18         res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
    19                          stdout=subprocess.PIPE,
    20                          stdin=subprocess.PIPE,
    21                          stderr=subprocess.PIPE)
    22 
    23         stderr=res.stderr.read()
    24         stdout=res.stdout.read()
    25         conn.send(stderr)
    26         conn.send(stdout)
    Server
     1 import socket
     2 
     3 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     4 res=s.connect_ex(('127.0.0.1',8888))
     5 
     6 while True:
     7     msg=input('>>: ').strip()
     8     if len(msg) == 0:continue
     9     if msg == 'quit':break
    10 
    11     s.send(msg.encode('utf-8'))
    12     act_res=s.recv(1024)
    13 
    14     print(act_res.decode('utf-8'),end='')
    Client

      同时执行多条命令之后,得到的结果可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种现象就是粘包。

    三、解决粘包问题

           问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个while循环接收完所有数据。

     1 import json
     2 import socket
     3 import struct
     4 import subprocess
     5 
     6 server = socket.socket()
     7 server.bind(('127.0.0.1',8080))
     8 server.listen(5)
     9 
    10 while True:
    11     conn,addr = server.accept()
    12     while True:
    13         try:
    14             msg = conn.recv(1024).decode('utf-8')
    15             if not msg : break
    16             obj = subprocess.Popen(msg,shell = True,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
    17             res = obj.stdout.read() + obj.stderr.read()
    18             dict = {'name':'Spenser','file_size':len(res),'info':'to be a better man'}
    19             json_dict = json.dumps(dict)
    20             #1.制作字典报头
    21             header = struct.pack('i',len(json_dict))
    22             #2.传送字典报头
    23             conn.send(header)
    24             #3.传送字典
    25             conn.send(json_dict.encode('utf-8'))
    26             #4.传送真实数据
    27             conn.send(res)
    28         except ConnectionResetError:
    29             break
    30     conn.close()
    server
     1 import socket
     2 import struct
     3 import json
     4 
     5 client = socket.socket()
     6 client.connect(('127.0.0.1',8080))
     7 
     8 while True:
     9     msg = input('>>>:').encode('utf-8')
    10     if len(msg) == 0:continue
    11     client.send(msg)
    12     # 1.先接受字典报头
    13     header_dict = client.recv(4)
    14     # 2.解析报头 获取字典的长度
    15     dict_size = struct.unpack('i',header_dict)[0]  # 解包的时候一定要加上索引0
    16     # 3.接收字典数据
    17     dict_bytes = client.recv(dict_size)
    18     dict_json = json.loads(dict_bytes.decode('utf-8'))
    19     # 4.从字典中获取信息
    20     print(dict_json)
    21     recv_size = 0
    22     real_data = b''
    23     while recv_size < dict_json.get('file_size'):  # real_size = 102400
    24         data = client.recv(1024)
    25         real_data += data
    26         recv_size += len(data)
    27     print(real_data.decode('gbk'))
    client
  • 相关阅读:
    mysql高级查询
    RabbitMq应用一的补充(RabbitMQ的应用场景)
    LNMP的并发配置和资源分配
    大神教你Nginx常用基础配置方案
    案例:配置apache和nginx的SSL加密传输协议
    Nginx配置服务器静态文件支持跨域访问
    菜鸟学习计划浅谈之Linux系统
    细述:nginx http内核模块提供的变量和解释
    如何在Linux中使用Firejail运行应用程序
    一款用于对 WiFi 接入点安全进行渗透测试的工具
  • 原文地址:https://www.cnblogs.com/spencerzhu/p/11317743.html
Copyright © 2020-2023  润新知