muduo网络库剖析——套接字Socket类

news2024/11/19 2:17:54

muduo网络库剖析——套接字Socket类

  • 前情
    • 从muduo到my_muduo
  • 概要
    • socket网络编程
    • socket编程接口介绍
      • 头文件
      • socket
      • bind
      • listen
      • accept
      • accept4
      • connect
  • 框架与细节
    • 成员
    • 函数
    • 使用方法
  • 源码
  • 结尾

前情

从muduo到my_muduo

作为一个宏大的、功能健全的muduo库,考虑的肯定是众多情况是否可以高效满足;而作为学习者,我们需要抽取其中的精华进行简要实现,这要求我们足够了解muduo库。

做项目 = 模仿 + 修改,不要担心自己学了也不会写怎么办,重要的是积累,学到了这些方法,如果下次在遇到通用需求的时候你能够回想起之前的解决方法就够了。送上一段话!

在这里插入图片描述

概要

socket网络编程

套接字(Socket)是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。它是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。简单来说,套接字是不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。

socket编程接口介绍

转自比特冬哥。

头文件

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>

socket

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

socket()函数类似于 open()函数,它用于创建一个网络通信端点(打开一个网络通信),如果成功则返回一个网络文件描述符,通常把这个文件描述符称为 socket 描述符(socket descriptor),这个 socket 描述符跟文件描述符一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。
该函数包括 3 个参数,如下所示:
domain
参数 domain 用于指定一个通信域;这将选择将用于通信的协议族。可选的协议族如下表所示:
在这里插入图片描述
对于 TCP/IP 协议来说,通常选择 AF_INET 就可以了,当然如果你的 IP 协议的版本支持 IPv6,那么可以选择 AF_INET6。

type
参数 type 指定套接字的类型,当前支持的类型有:
在这里插入图片描述
protocol
参数 protocol 通常设置为 0,表示为给定的通信域和套接字类型选择默认协议。当对同一域和套接字类型支持多个协议时,可以使用 protocol 参数选择一个特定协议。在 AF_INET 通信域中,套接字类型为SOCK_STREAM 的默认协议是传输控制协议(Transmission Control Protocol,TCP 协议)。

在 AF_INET 通信域中,套接字类型为 SOCK_DGRAM 的默认协议时 UDP。
调用 socket()与调用 open()函数很类似,调用成功情况下,均会返回用于文件 I/O 的文件描述符,只不过对于 socket()来说,其返回的文件描述符一般称为 socket 描述符。当不再需要该文件描述符时,可调用close()函数来关闭套接字,释放相应的资源。

如果 socket()函数调用失败,则会返回-1,并且会设置 errno 变量以指示错误类型。

bind

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind()函数用于将一个 IP 地址或端口号与一个套接字进行绑定(将套接字与地址进行关联)。将一个客户端的套接字关联上一个地址没有多少新意,可以让系统选一个默认的地址。一般来讲,会将一个服务器的套接字绑定到一个众所周知的地址—即一个固定的与服务器进行通信的客户端应用程序提前就知道的地址(注意这里说的地址包括 IP 地址和端口号)。因为对于客户端来说,它与服务器进行通信,首先需要知道服务器的 IP 地址以及对应的端口号,所以通常服务器的 IP 地址以及端口号都是众所周知的。

调用 bind()函数将参数 sockfd 指定的套接字与一个地址 addr 进行绑定,成功返回 0,失败情况下返回-1,并设置 errno 以提示错误原因。

关于sockaddr的讲解,请看我InetAddress那篇文章。

listen

listen()函数只能在服务器进程中使用,让服务器进程进入监听状态,等待客户端的连接请求,listen()函数在一般在 bind()函数之后调用,在 accept()函数之前调用,它的函数原型是:

int listen(int sockfd, int backlog);

无法在一个已经连接的套接字(即已经成功执行 connect()的套接字或由 accept()调用返回的套接字)上执行 listen()。

参数 backlog 用来描述 sockfd 的等待连接队列能够达到的最大值。在服务器进程正处理客户端连接请求的时候,可能还存在其它的客户端请求建立连接,因为 TCP 连接是一个过程,由于同时尝试连接的用户过多,使得服务器进程无法快速地完成所有的连接请求,那怎么办呢?直接丢掉其他客户端的连接肯定不是一个很好的解决方法。因此内核会在自己的进程空间里维护一个队列,这些连接请求就会被放入一个队列中,服务器进程会按照先来后到的顺序去处理这些连接请求,这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限,这个 backlog 参数告诉内核使用这个数值作为队列的上限。而当一个客户端的连接请求到达并且该队列为满时,客户端可能会收到一个表示连接失败的错误,本次请求会被丢弃不作处理。

accept

服务器调用 listen()函数之后,就会进入到监听状态,等待客户端的连接请求,使用 accept()函数获取客户端的连接请求并建立连接。函数原型如下所示:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

为了能够正常让客户端能正常连接到服务器,服务器必须遵循以下处理流程:
① 调用 socket()函数打开套接字;
② 调用 bind()函数将套接字与一个端口号以及 IP 地址进行绑定;
③ 调用 listen()函数让服务器进程进入监听状态,监听客户端的连接请求;
④ 调用 accept()函数处理到来的连接请求。

accept()函数通常只用于服务器应用程序中,如果调用 accept()函数时,并没有客户端请求连接(等待连接队列中也没有等待连接的请求),此时 accept()会进入阻塞状态,直到有客户端连接请求到达为止。当有客户端连接请求到达时,accept()函数与远程客户端之间建立连接,accept()函数返回一个新的套接字。这个套接字与 socket()函数返回的套接字并不同,socket()函数返回的是服务器的套接字(以服务器为例),而accept()函数返回的套接字连接到调用 connect()的客户端,服务器通过该套接字与客户端进行数据交互,譬如向客户端发送数据、或从客户端接收数据。

所以,理解 accept()函数的关键点在于它会创建一个新的套接字,其实这个新的套接字就是与执行
connect()(客户端调用 connect()向服务器发起连接请求)的客户端之间建立了连接,这个套接字代表了服务器与客户端的一个连接。如果 accept()函数执行出错,将会返回-1,并会设置 errno 以指示错误原因。

参数 addr 是一个传出参数,参数 addr 用来返回已连接的客户端的 IP 地址与端口号等这些信息。
参数addrlen 应设置为 addr 所指向的对象的字节长度,如果我们对客户端的 IP 地址与端口号这些信息不感兴趣,可以把 arrd 和 addrlen 均置为空指针 NULL。

accept4

这个函数相比于accept多了一些接受的选项,如SOCK_NONBLOCK和SOCK_CLOEXEC.

SOCK_NONBLOCK是一个套接字选项,用于设置或查询套接字的阻塞模式。在阻塞模式下,套接字会等待操作完成或出现错误才会返回,而在非阻塞模式下,套接字会立即返回,不会等待操作完成或出现错误。等价于O_NONBLOCK。

SOCK_CLOEXEC是一个套接字选项,用于设置或查询套接字的close-on-exec标志位。当进程执行新程序时,如果套接字的close-on-exec标志位被设置,则该套接字将被自动关闭。设置close-on-exec标志位的好处是,当进程执行新程序时,可以避免套接字被继承到新程序中,从而避免了潜在的安全问题。

connect

connect()函数原型如下所示:

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

该函数用于客户端应用程序中,客户端调用 connect()函数将套接字 sockfd 与远程服务器进行连接,参数 addr 指定了待连接的服务器的 IP 地址以及端口号等信息,参数 addrlen 指定了 addr 指向的 struct sockaddr对象的字节大小。

客户端通过 connect()函数请求与服务器建立连接,对于 TCP 连接来说,调用该函数将发生 TCP 连接的握手过程,并最终建立一个 TCP 连接,而对于 UDP 协议来说,调用这个函数只是在 sockfd 中记录服务器IP 地址与端口号,而不发送任何数据。

函数调用成功则返回 0,失败返回-1,并设置 errno 以指示错误原因。

框架与细节

成员

在这里插入图片描述
套接字成员。

函数

TCP_NODELAY

setsockopt(sockfd_, IPPROTO_IP, TCP_NODELAY, &flag, sizeof flag);

这段代码是C或C++语言中用于设置套接字选项的函数调用。具体来说,它设置了一个TCP套接字的Nagle算法的禁用选项。

  • setsockopt() 是一个用于设置套接字选项的函数。
  • sockfd_ 是要设置选项的套接字的文件描述符。
  • IPPROTO_IP 是协议级别,表示我们正在设置IP层的选项。
  • TCP_NODELAY 是一个选项,用于禁用Nagle算法。Nagle算法是一种拥塞控制机制,它用于减少网络上的小包数量,以提高数据传输的效率。然而,在某些应用场景中,我们可能需要更快的数据传输速度,此时可以禁用Nagle算法。
  • &flag 是指向一个整数的指针,该整数表示是否禁用Nagle算法(flag 为非零值表示禁用,为零表示启用)。
  • sizeof flag 是选项的长度。

综合来看,这段代码的作用是禁用套接字sockfd_上的Nagle算法,以加快数据传输速度。这在实时应用或需要低延迟的应用中可能是有用的。

SO_REUSEADDR

setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof flag);

这段代码是C或C++语言中用于设置套接字选项的函数调用。具体来说,它设置了一个套接字的地址复用选项。

setsockopt() 是一个用于设置套接字选项的函数。
sockfd_ 是要设置选项的套接字的文件描述符。
SOL_SOCKET 是协议级别,表示我们正在设置套接字级的选项。
SO_REUSEADDR 是一个选项,用于允许套接字在关闭后立即重新使用其地址。这在进行服务器编程时特别有用,因为在服务器重启或关闭后,它通常需要立即重新绑定到相同的地址和端口。
&flag 是指向一个整数的指针,该整数表示是否启用地址复用(flag 为非零值表示启用,为零表示禁用)。
sizeof flag 是选项的长度。
综合来看,这段代码的作用是启用套接字sockfd_上的地址复用功能,以便在关闭后立即重新使用相同的地址。这在服务器编程中是常见的做法,以避免由于地址绑定延迟而导致的延迟或问题。

SO_REUSEPORT

setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof flag);

这段代码是C或C++语言中用于设置套接字选项的函数调用。具体来说,它设置了一个套接字的端口复用选项。

setsockopt() 是一个用于设置套接字选项的函数。
sockfd_ 是要设置选项的套接字的文件描述符。
SOL_SOCKET 是协议级别,表示我们正在设置套接字级的选项。
SO_REUSEPORT 是一个选项,用于允许多个套接字绑定到同一个端口上。这在进行服务器编程时特别有用,特别是在使用如Nginx这样的高性能服务器时,它可以允许多个工作进程绑定到同一个端口上,从而实现负载均衡和容错。
&flag 是指向一个整数的指针,该整数表示是否启用端口复用(flag 为非零值表示启用,为零表示禁用)。
sizeof flag 是选项的长度。
综合来看,这段代码的作用是启用套接字sockfd_上的端口复用功能,以便允许多个套接字绑定到同一个端口上。这在实现高性能服务器和负载均衡时是常见的做法。

SO_KEEPALIVE

setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof flag);

这行代码具体设置了一个套接字的 “Keep-Alive” 选项。让我们逐一解析这行代码的各个部分:

sockfd_:
这是要设置选项的套接字的文件描述符。
SOL_SOCKET:
这是协议级别,表示我们正在设置的是套接字级的选项,而不是某个特定于协议的选项。
SO_KEEPALIVE:
这是一个套接字选项,用于启用或禁用 “Keep-Alive” 功能。启用这个功能后,如果套接字在一段时间内没有活动,操作系统会发送一个数据包来检查连接是否仍然有效。这对于检测网络故障或对端系统故障非常有用。
&flag:
这是一个指向整数的指针,表示是否启用 “Keep-Alive” 功能。如果 flag 为非零值,则启用该功能;如果为零,则禁用。
sizeof flag:
这表示选项的长度,这里是 flag 变量的大小。
总结:这行代码用于设置 sockfd_ 套接字的 “Keep-Alive” 功能。如果 flag 非零,则启用该功能;如果为零,则禁用。启用 “Keep-Alive” 可以帮助检测和预防网络连接问题。

使用方法

源码

//Socket.h
#pragma once 

#include <sys/socket.h>
#include <netinet/tcp.h>

#include "Log.h"
#include "noncopyable.h"
#include "InetAddress.h"

class Socket : noncopyable {
public:
    explicit Socket(int sockfd) : sockfd_(sockfd) {} 
    ~Socket();

    int fd() const { return sockfd_; }
    void listen();
    void bind(const InetAddress& localAddr);
    int accept(InetAddress& peerAddr);

    void setTcpNoDelay(bool on);
    void setReuseAddr(bool on);
    void setReusePort(bool on);
    void setKeepAlive(bool on);
private:
    const int sockfd_;
};
//Socket.cc
#include "Socket.h"

Socket::~Socket() {
    ::close(sockfd_);
}

void Socket::listen() {
    if(::listen(sockfd_, 1024) == -1) {
        LOG_FATAL("%s--%s--%d--%d : listen error\n", __FILE__, __FUNCTION__, __LINE__, errno);
    }
}

void Socket::bind(const InetAddress& localAddr) {
    if (::bind(sockfd_, (sockaddr*)localAddr.getSockAddr(), sizeof(sockaddr)) != 0) {
        LOG_FATAL("%s--%s--%d--%d : bind error\n", __FILE__, __FUNCTION__, __LINE__, errno);
    }
}

int Socket::accept(InetAddress& peerAddr) {
    sockaddr_in* sa;
    bzero(sa, sizeof sa);
    socklen_t st = sizeof(sa);
    int connfd = ::accept4(sockfd_, (sockaddr*)sa, &st, SOCK_NONBLOCK | SOCK_CLOEXEC);
    if (connfd >= 0) {
        peerAddr.setSockAddr(*sa);
    }
    return connfd;
}

void Socket::setTcpNoDelay(bool on) {
    int flag = on ? 1 : 0;
    ::setsockopt(sockfd_, IPPROTO_IP, TCP_NODELAY, &flag, sizeof flag);
}

void Socket::setReuseAddr(bool on) {
    int flag = on ? 1 : 0;
    ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof flag);
}

void Socket::setReusePort(bool on) {
    int flag = on ? 1 : 0;
    ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof flag);
}

void Socket::setKeepAlive(bool on) {
    int flag = on ? 1 : 0;
    ::setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof flag);
}

结尾

以上就是套接字Socket类的相关介绍,以及我在进行项目重写的时候遇到的一些问题,和我自己的一些心得体会。发现写博客真的会记录好多你的成长,而且对于一个好的项目,写博客也是证明你确实有过深度思考,并且在之后面试或者工作时遇到同样的问题能够进行复盘的一种有效的手段。所以,希望uu们也可以像我一样,养成写博客的习惯,逐渐脱离菜鸡队列,向大佬前进!!!加油!!!

也希望我能够完成muduo网络库项目的深度学习与重写,并在功能上能够拓展。也希望在完成这个博客系列之后,能够引导想要学习muduo网络库源码的人,更好地探索这篇美丽繁华的土壤。致敬chenshuo大神!!!

鉴于博主只是一名平平无奇的大三学生,没什么项目经验,所以可能很多东西有所疏漏,如果有大神发现了,还劳烦您在评论区留言,我会努力尝试解决问题!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1385998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BPF 程序与信号交互大揭秘

本文地址 &#xff1a; BPF 程序与信号交互大揭秘 | 深入浅出 eBPF 原文&#xff1a;Signaling from within: how eBPF interacts with signals 1. 背景2. 动机3. 场景&#xff1a;拦截 openat(2)4. 内核如何处理 SIGKILL 信号&#xff1f;5. 什么信号要后置处理6. 通过 BPF程…

arcgis javascript api4.x以basetilelayer方式加载arcgis发布的栅格切片服务

需求&#xff1a; 以arcgis js api的basetilelayer加载arcgis发布的栅格切片服务 效果图&#xff1a; 其中和tileinfo和lods&#xff0c;这样获取&#xff1a; https://map.geoq.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer/?fpjson urltemplate&#xff1a; …

Pod的控制器

Pod的控制器是什么&#xff1f; pod控制器&#xff1a;工作负载均衡。workload。用于管理pod的中间层。确保pod资源符合预期的状态。 预期状态&#xff1a; 副本数 容器的重启策略 镜像拉取策略 pod出现故障时的重启等等 Pod控制器的类型 1、 replicaSet&#xff1a;指…

RC4(CTFshow re2)

基本原理 RC4属于对称密码算法中的流密码加密算法 什么是对称密码&#xff1f; 使用同一个密钥进行加密和解密 什么是流密码&#xff1f; 一个字节一个字节的进行加密/解密 RC4密钥长度是可以变的&#xff0c;面向字节操作 它以一个足够大的表s为基础 对表进行非线性变换&…

Web3去中心化存储:重新定义云服务

随着Web3技术的崭露头角&#xff0c;去中心化存储正在成为数字时代云服务的全新范式。传统的云服务依赖于中心化的数据存储架构&#xff0c;而Web3的去中心化存储则为用户带来了更安全、更隐私、更可靠的数据管理方式&#xff0c;重新定义了云服务的未来。 1.摒弃中心化的弊端 …

酒类销售新模式:用户裂变,利润倍增的秘诀

在当今竞争激烈的市场环境中&#xff0c;如何设计出既吸引用户又能带来高利润的商业模式&#xff0c;成为了企业成功的关键。酒类销售也不例外。最近&#xff0c;一种创新的酒类销售模式在市场上悄然兴起&#xff0c;它不仅让消费者在购买中获得实实在在的优惠&#xff0c;还通…

java基础之线程知识点

线程 进程的概念 操作系统(OS)中并发(同时)执行的多个程序任务 进程的特点 宏观并行,微观串行 在一个时间段内,CPU会将时间段划分为若干个时间片,一个时间片是能被一个程序拥有,且只有拥有时间片的程序才能执行自身内容,所以当时间片的划分足够细小,交替频率足够快,就会形…

keycloak部署

https://downloads.jboss.org/keycloak/11.0.2/keycloak-11.0.2.zip 1.上传zip 并解压 uzip keycloak-11.0.2.zip 2.创建mysql数据库 CREATE SCHEMA keycloak DEFAULT CHARACTER SET utf8 ; 3.安装mysql的jdbc驱动 下载mysql的JDBC驱动&#xff08;mysql-connector-java-8…

基于ssm的校园二手交易平台的设计与开发+vue论文

摘 要 社会和科技的不断进步带来更便利的生活&#xff0c;计算机技术也越来越平民化。二十一世纪是数据时代&#xff0c;各种信息经过统计分析都可以得到想要的结果&#xff0c;所以也可以更好的为人们工作、生活服务。二手物品是学校里最常见的物品&#xff0c;把二手物品再次…

sql | 学生参加各科考试次数

学生表: Students------------------------ | Column Name | Type | ------------------------ | student_id | int | | student_name | varchar | ------------------------ 在 SQL 中&#xff0c;主键为 student_id&#xff08;学生ID&#xff09;。 该表内的每…

海格里斯HEGERLS仓储货架生产厂家|载荷1.5T运行速度1.7~2m/s的智能四向穿梭车系统

四向穿梭车立体库是近年来出现的一种智能型密集系统&#xff0c;通过使用四向穿梭车在货架的水平和纵向轨道上运行来搬运货物&#xff0c;一台四向穿梭车就能完成货物的搬运工作&#xff0c;大大提高了工作效率。同时配合提升机、自动化仓库管理系统(WMS)和仓库调度系统(WCS)&a…

Express框架搭建项目

1. Express简介 EXpress&#xff1a; 精简的、灵活的Node.js Web程序框架&#xff0c;为构建单页、多页及混合的Web程序提供了一系列健壮的功能特性。 精简&#xff1a; Express在你的想法和服务器之间充当薄薄的一层&#xff0c;尽量少干预你&#xff0c;在你充分表达自己思…

v-if 实现不同的状态样式

目录 一、实现思路 二、实现步骤 案例一&#xff1a; ①view部分展示 ②JavaScript 内容 ④ 效果展示 案例二&#xff1a; ①view部分展示 ②JavaScript 内容 ④ 效果展示 ​编辑 一、实现思路 通过v-for循环获取数据并进行判断该条记录中status的状态 给不同的状态赋值&am…

引领安全创新 | 安全狗方案入选工信部《2023年工业和信息化领域数据安全典型案例名单》

近日&#xff0c;工业和信息化部网络安全管理局公布了2023年工业和信息化领域数据安全典型案例名单。 安全狗与厦门卫星定位应用股份有限公司、中移 (上海) 信息通信科技有限公司联合申报的智慧交通云数据安全与隐私保障典型案例也成功入选。 厦门服云信息科技有限公司&#xf…

WebStom中代码美化工具prettier的配置

如果你的项目使用到了prettier代码美化工具之后&#xff0c;使用ctrlaltL调整代码格式的时候会发现&#xff0c;代码没有被正确格式化&#xff0c;这是因为prettier代码美化工具没有设置格式化vue代码的设置。在下面中的run for files的括号里面加上vue即可 最后一步就是确保es…

【已解决】c++如何打印变量的类型

本博文源于笔者正在编写的c代码&#xff0c;在c/c中我们经常用auto去接一个变量&#xff0c;这样我们既可以不用知道变量或函数结果的类型&#xff0c;就可以轻松愉快编码&#xff0c;如果想要知道变量的类型呢&#xff1f;那就需要这样一个函数。 问题再现 想要用函数去打印…

【web】springboot3 生成本地文件 url

文章目录 流程效果静态资源访问ServiceServiceImplController 流程 avatar_dir&#xff1a;请求图片在服务端的存放路径user.dir&#xff1a;项目根目录 效果 静态资源访问 application.yml 设置静态文件存储路径custom:upload:avatar_dir: ${user.dir}/avatar_dir/avatar_d…

基于Java SSM框架实现在线作业管理系统项目【项目源码】

基于java的SSM框架实现在线作业管理系统演示 JSP技术 JSP技术本身是一种脚本语言&#xff0c;但它的功能是十分强大的&#xff0c;因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时&#xff0c;它可以使显示逻辑和内容分开&#xff0c;这就极大的方便了运动员的需求…

2024年初会报名照片要求(必须白底哦)

24初级会计报名照片要求 近期彩色标准1寸、(白色背景)&#xff0c; jpg格式&#xff0c;大于10KB ,像素>295*413. 初级会计考试报名照片要求为本人近期正面、免冠、清晰完整的证件电子照。 初级会计报名照片应显示报考人员双肩、双耳、双眉&#xff0c;不得佩戴首饰&#xf…

基地动态|天府新区兴隆街道领导一行莅临天府锋巢直播产业基地考察交流

11月30日&#xff0c;天府新区兴隆街道党工委委员周杰、兴隆街道营商环境办主任章瑞芸、兴隆湖社区党委书记等领导一行莅临天府锋巢直播产业基地考察交流。天府锋巢直播产业基地运营团队、招商代表、入驻企业代表陪同参与。 考察中&#xff0c;基地运营团队向天府新区兴隆街道领…