C/S模型测试及优化

1

1.1代码示例

#include<stdio.h>
#include<stdio.h>#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#include <sys/stat.h>
#include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int sockfd=0;int ret=0;struct sockaddr_in seraddr;char tmpbuff[4096]={"I need some offers"};int cnt=0;ssize_t nsize=0;/* 1 创建网络套接字 */sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}/* 2 初始化网络地址结构体 */seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");/* 3 发送连接请求 */ret=connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to connect");return -1;}/* 4 客户端与服务器交互 */while(1){
#if 0/* 4.1 清空发送缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 4.2 拼接数据 */sprintf(tmpbuff,"client send:### %d",cnt);cnt++;/* 4.3 发送数据到网络套接字 */nsize=send(sockfd,tmpbuff,strlen(tmpbuff),0);if(-1==nsize){perror("fail to send");return -1;}
#endif#if 1/* 清空接收缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 接收网络套接字数据 */nsize=recv(sockfd,tmpbuff,sizeof(tmpbuff),0);if(-1==nsize){perror("fail to recv");return -1;}
#endif/* 显示接收数据 */printf("client recv:### %s\n",tmpbuff);}/* 5 关闭网络套接字 */close(sockfd);return 0;
}int main(void)
{int sockfd=0;struct sockaddr_in seraddr;int ret=0; int confd=0;char tmpbuff[4096]={0};ssize_t nsize=0;/* 1 创建网络套接字 */sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}/* 2 初始化网络地址结构体 */seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");/* 3 绑定网络套接字 */ret=bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to bind");return -1;}/* 4 监听网络套接字 */ret=listen(sockfd,10);if(-1==ret){perror("fail to listen");return -1;}/* 5 服务器与客户端交互 */while(1){/* 5.1 创建通信套接字-阻塞等待网络套接字连接请求*/confd=accept(sockfd,NULL,NULL);if(-1==confd){perror("fail to accept");return -1;}#if 0/* 5.2 清空接收缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 5.3 接收通信套接字数据-并做接收完成处理 */nsize=recv(confd,tmpbuff,sizeof(tmpbuff),0);if(-1==nsize){perror("fail to recv");return -1;}else if(0==nsize){return 0;}
#endif/* 5.2 清空发送缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 5.4 拼接 */sprintf(tmpbuff,"server send:### %s",tmpbuff);/* 5.5 发送 */nsize=send(confd,tmpbuff,strlen(tmpbuff),0);if(-1==nsize){perror("fail to send");return -1;}}/* 6 关闭通信套接字 */close(confd);/* 7 关闭网络套接字 */close(sockfd);return 0;
}

1.2运行结果

(1)运行服务器
(2)运行客户端现象如下:客户端发生阻塞

在这里插入图片描述

(1)关闭服务器:客户端不阻塞-说明recv函数为非阻塞状态

在这里插入图片描述

总结:
(1)如果将服务器accept函数放在while循环内部:同时运行客户端与服务器,可以发现服务器可以与多个客户端建立连接(解决的问题-服务器并发访问)。
(2)但是只能进行一次数据发送(虽然解决了服务器的并发访问问题,但是对于大量的数据传输却手足无措)小意外:当服务器端退出,此时客户端不再阻塞,正常执行函数体。(这就说明了,此时recv函数为非阻塞状态=》那么服务器和客户端同时运行,为什么会发生阻塞?)补充:
(1)如果将服务器端accept函数放在while循环外部(对比TCP文件传输):1)只有一个客户端能够与服务器建立连接并进行数据收发;其它客户端被阻塞,无法与服务器建立连接。(问题:(1)服务器只能与一个客户端建立连接?(2)那么如何解决这个问题?(3)是从服务端解决这个问题,还是从客户端解决这个问题?	先解决问题(3):显然,要解决这个问题肯定是要从服务器端去解决--客户端是向服务器端发起连接请求,那么具体是否能够建立连接,显然是取决于服务器端的意愿和能力;所以,多个客户端向服务器端发起连接请求,能不能实现的关键在于服务器能不能接受多个客户端接入,服务器端是否允许多个客户端接入。	下面再解决问题(2):解决这个问题,其实用一句话来表述就是解决服务器并发访问问题,这个问题后面专项解决,现在只需要明白所面临的问题是服务器并发访问的问题即可。)(2)如果将connect函数放在循环外部,将accept函数放在循环外部,此时意味着:客户端与服务器端第一次建立连接,可以发送一次数据;发完数据接着进行第二次,第三次。。。连接请求;此时当然是报错!因为同一个网络套接字只能建立一次连接,不能重复建立连接(这是由TCP通信机制决定的);但是这种方式可以将服务器同时与多个客户端建立连接。。。。。。。。。。。。。。总结一下就是:客户端与服务器端要进行多次请求连接-建立连接;那么每进行一次通信,都必须关闭(close)通信套接字(已经建立三次握手,四次挥手连接的套接字confd-accept)。

在这里插入图片描述

2 多线程解决TCP并发问题

2.1 源码示例

/*************************************************************************> File Name: client.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月01日 星期六 10时44分42秒************************************************************************/#include<stdio.h>#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#include <sys/stat.h>
#include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int sockfd=0;struct sockaddr_in seraddr;int ret=0;ssize_t nsize=0;char sendbuffer[4096]={"|c-send|"};char recvbuffer[4096]={"|c-recv|"};int cnt=100;sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);//本地字节序转换为网络大端字节序seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");//字符串IP转为内存中的IPret=connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to connect");return -1;}while(1){	memset(sendbuffer,0,sizeof(sendbuffer));sprintf(sendbuffer,"< %d >",--cnt);nsize=send(sockfd,sendbuffer,sizeof(sendbuffer),0);if(-1==nsize){perror("fail to send");return -1;}printf("client send: %s\n",sendbuffer);sleep(1);memset(recvbuffer,0,sizeof(recvbuffer));nsize=recv(sockfd,recvbuffer,sizeof(recvbuffer),0);if(-1==nsize){perror("fail to recv");return -1;}printf("client recv: %s\n",recvbuffer);sleep(1);}return 0;
}
/*************************************************************************> File Name: server.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月01日 星期六 14时17分47秒************************************************************************/#include<stdio.h>#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#include <sys/stat.h>
#include <fcntl.h>#include <unistd.h>#include <string.h>#include <pthread.h>void *handle_tcp_client(void *arg);int main(void)
{pthread_t tid=0;pthread_attr_t attr;int sockfd=0;struct sockaddr_in seraddr;int ret=0;int confd=0;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to sockfd");return -1;}seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");ret=bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));//警告: 结构体类型强制转换?if(-1==ret){perror("fail to bind");return -1;}ret=listen(sockfd,10);if(-1==ret){perror("fail to listen");return -1;}while(1){confd=accept(sockfd,NULL,NULL);if(-1==confd){perror("fail to accept");return -1;}
#if 0/* <1> 线程回调函数传参-粗心传参*/pthread_create(&tid,&attr,handle_tcp_client,&confd);
#endif
#if 1/* <1> 线程回调函数传参-细节优化*/pthread_create(&tid,&attr,handle_tcp_client,confd);//线程回调函数传参,传的是指针,这里直接传值?
#endif}close(sockfd);return 0;
}void *handle_tcp_client(void *arg)
{ssize_t nsize=0;char sendbuffer[4096]={"|s-send|"};char recvbuffer[4096]={"|s-recv|"};
#if 0/* <1> 线程回调函数传参-粗心传参*/int confd=*(int *)arg;
#endif
#if 1/* <1> 线程回调函数传参-细节优化*/int confd=arg;
#endifint cnt=0;while(1){memset(recvbuffer,0,sizeof(recvbuffer));nsize=recv(confd,recvbuffer,sizeof(recvbuffer),0);if(-1==nsize){perror("fail to recv");return NULL;}else if(0==nsize){return NULL;}printf("server recv: %s\n",recvbuffer);sleep(1);memset(sendbuffer,0,sizeof(sendbuffer));sprintf(sendbuffer,"< %d >",++cnt);nsize=send(confd,sendbuffer,strlen(sendbuffer),0);if(-1==nsize){perror("fail to send");return NULL;}printf("server send: %s\n",sendbuffer);sleep(1);}return NULL;
}

2.2 运行结果

在这里插入图片描述

2.3 分析总结

服务器端:两次接收:两个客户端与服务器端建立连接,接受两个客户端分别发送过来的数据;两次发送:服务器端与两个客户端建立连接,发送数据时向两个客户端分别发送一次数据。客户端:一次发送:向服务器端发送一次数据。一次接收:接受服务器端发送过来的数据。问题:(1)如果连入多个客户端,那么就创建了多个通信套接字(confd);服务器端创建多线程的时候,为回调函数传参问题:1)回调函数传参传【&confd】:那么后建立的服务器端与客户端的连接产生的文件描述符(confd)就会将先建立的服务器端与客户端的连接产生的文件描述符(confd)覆盖;这将会导致不同的客户端的不同数据请求得到服务器端的数据响应是一样的(即只有一个客户端可以收到自己想要的数据,而其它的客户端收到的将不是自己请求的数据)。2)回调函数传参传【confd】:就可以解决先建立连接产生的文件描述符被覆盖的问题。(同时编译过程中产生2个警告!)(2)运行效果:		

在这里插入图片描述

3 IO多路复用解决TCP并发问题

3.1 select

3.1.1 源码示例

3.1.1 客户端
/*************************************************************************> File Name: client.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月03日 星期一 16时12分48秒************************************************************************/#include<stdio.h>#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#include <sys/stat.h>
#include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int sockfd=0;struct sockaddr_in seraddr;int ret=0;ssize_t nsize=0;char sendbuffer[4096]={0};char recvbuffer[4096]={0};int send_cnt=1;
//    int recv_cnt=99;sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");ret=connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to connect");return -1;}while(1){memset(sendbuffer,0,sizeof(sendbuffer));sprintf(sendbuffer,"|%-3d|",send_cnt++);nsize=send(sockfd,sendbuffer,sizeof(sendbuffer),0);if(-1==nsize){perror("fail to send");return -1;}printf("client send: %s\n",sendbuffer);memset(recvbuffer,0,sizeof(recvbuffer));nsize=recv(sockfd,recvbuffer,sizeof(recvbuffer),0);if(-1==nsize){perror("fail to recv");return -1;}printf("client recv: %s\n",recvbuffer);/* 方便查看运行结果*/sleep(3);}close(sockfd);return 0;
}
3.1.2 服务器端
/*************************************************************************> File Name: server.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月03日 星期一 17时01分50秒************************************************************************/#include<stdio.h>#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#include <sys/stat.h>
#include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int sockfd=0;struct sockaddr_in seraddr;int ret=0;int confd=0;int maxfd=0;ssize_t nsize=0;char sendbuffer[4096]={0};char recvbuffer[4096]={0};int send_cnt=99;fd_set rdfds;fd_set tmpfds;sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");ret=bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to bind");return -1;}ret=listen(sockfd,10);if(-1==ret){perror("fail to listen");return -1;}/* 文件描述符集操作 */FD_ZERO(&rdfds);//初始化文件描述符集合FD_SET(sockfd,&rdfds);//添加文件描述符至文件描述符集合while(1){/* 初始化监听文件描述符集合 */tmpfds=rdfds;/* 监听文件描述符集合 */ret=select(sockfd+1,&tmpfds,NULL,NULL,NULL);if(-1==ret){perror("fail to select");return -1;}/* 查询文件描述符集合中文件描述符状态*/if(FD_ISSET(sockfd,&tmpfds)){confd=accept(sockfd,NULL,NULL);/* 注意: 异常处理(3个操作) */if(-1==confd){perror("fail to accept");FD_CLR(sockfd,&rdfds);//将套接字文件描述符从文件描述符集合中删除close(sockfd);//关闭套接字文件continue;//既然建立TCP连接失败,跳过TCP收发过程也理所当然}FD_SET(confd,&rdfds);
//			maxfd = maxfd > confd ? maxfd : confd;}/* 查询文件描述符集合中文件描述符状态 */if(FD_ISSET(sockfd,&tmpfds)){memset(recvbuffer,0,sizeof(recvbuffer));nsize=recv(confd,recvbuffer,sizeof(recvbuffer),0);if(-1==nsize){perror("fail to recv");return -1;}printf("server recv: %s\n",recvbuffer);memset(sendbuffer,0,sizeof(sendbuffer));sprintf(sendbuffer,"|%-3d|",send_cnt--);nsize=send(confd,sendbuffer,sizeof(sendbuffer),0);if(-1==nsize){perror("fail to send");return -1;}printf("server send: %s\n",sendbuffer);}/* 方便查看运行结果*/sleep(3);}close(confd);close(sockfd);
}
3.1.3 服务器端改进

3.1.2 运行结果

3.1.3 分析总结

3.2 poll

3.2.1 源码示例

3.2.2 运行结果

3.2.3 分析总结

3.3 epoll

3.3.1 源码示例

3.3.2 运行结果

3.3.3 分析总结

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

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

相关文章

计算机基础知识

计算机基础知识 计算机是如何工作的 在本节内容中,介绍了计算机核心工作机制,计算机结构,框架等,计算机需求在人类的历史中是广泛存在的,发展大体经历了从一般计算工具到机械计算机到目前的电子计算的发展过程 文章目录 计算机基础知识一、冯诺依曼体系结构二、CPUCPU的核心参…

STM 32_HAL_SDIO_SD卡

STM32的SDIO&#xff08;Secure Digital Input Output&#xff09; 接口是一种用于SD卡和MMC卡的高速数据传输接口。它允许STM32微控制器与多种存储卡和外设进行通信&#xff0c;支持多媒体卡&#xff08;MMC卡&#xff09;、SD存储卡、SDI/O卡和CE-ATA设备。STM32的SDIO控制器…

JAVA-学习

一、垃圾回收机制 1、为什么要进行垃圾回收机制 如果不进行垃圾回收&#xff0c;内存迟早都会被消耗空&#xff0c;因为我们在不断的分配内存空间而不进行回收。除非内存无限大&#xff0c;我们可以任性的分配而不回收&#xff0c;但是事实并非如此。所以&#xff0c;垃圾回收…

【大模型】在大语言模型的架构中,Transformer有何作用?

Transformer在大语言模型架构中的作用 Transformer是一种用于序列到序列&#xff08;Seq2Seq&#xff09;任务的深度学习模型&#xff0c;由Vaswani等人于2017年提出。在大语言模型&#xff08;LLM&#xff09;的架构中&#xff0c;Transformer扮演着关键的角色&#xff0c;它…

Flink中因java的泛型擦除导致的报错及解决

【报错】 Exception in thread "main" org.apache.flink.api.common.functions.InvalidTypesException: The return type of function Custom Source could not be determined automatically, due to type erasure. You can give type information hints by using th…

【php实战项目训练】——thinkPhP的登录与退出功能的实现,让登录退出畅通无阻

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

Mendix 创客访谈录|Mendix助力开发高手10日交付复杂应用,且支持移动端呈现

本期创客 莊秉勳 布鲁科技技术顾问 各位Mendix社群的夥伴好&#xff0c;我是莊秉勳&#xff0c;大家也可以叫我Danny。 我大學是資訊科學背景&#xff0c;在與Mendix相遇前&#xff0c;曾在一上市製造企業&#xff0c;擔任軟體工程師&#xff0c;負責企業內部軟體開發&#xf…

Virtualbox 安装unbuntu + qemu

0. 前言 关于 Virualbox 安装虚拟机的优秀文章太多了&#xff0c;笔者主要是着重梳理一些安装小细节&#xff0c;利己利人&#xff01;&#xff01; 如果需要保姆式的安装教程&#xff0c;可以查看后续的参考链接。 1. VirtualBox 的安装 直接去官网搜索最近的软件即可&…

js每日十题(二)

1. 6.3 js第6题 以下结语句中&#xff0c;返回true的是&#xff1f; A !![] B 1’1’ C nullundefined D !!’’ 答&#xff1a; A选项&#xff0c;由于数组属于对象类型&#xff0c;所以空的数组转换成布尔型是true&#xff0c;前置&#xff01;&#xff01;&#xff0c;两次取…

【paper】环形虚拟管内的多无人机协同目标包围

Multi-UAV cooperative target encirclement within an annular virtual tube2022.8ELSEVIER Aerospace Science and Technology【Q1 5.6】Yan Gao 全权 北航 Q1 Background&#xff1a;本文试图解决一个什么样的问题&#xff1f; 多无人机对单个静态目标进行连续包围任务&…

基于聚类和回归分析方法探究蓝莓产量影响因素与预测模型研究附录

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 目录 背景数据说明数据来源思考 附录数据预处理导入包以及数据读取数据预览数据处理 相关性分析聚类分析数据处理确定聚类数建立k均值聚类模型 …

12- Redis 中的 链表 数据结构

Redis 的 List 对象的底层实现之一就是链表。C 语言本身没有链表这个数据结构&#xff0c;所以 Redis 自己设计了一个链表数据结构。 1. 链表节点结构设计 先来看看【链表节点】结构的样子&#xff1a; typedef struct listNode {//前置节点struct listNode *prev;//后置节点…

liunx配置网络的命令

liunx配置网络的命令 文章目录 liunx配置网络的命令ifconfig命令查看路由表信息netstat命令ss命令lsof命令ping 命令nslookup命令 ifconfig命令 ifconfig:显示正在工作的网卡&#xff0c;启动的设备 ifconfig -a 展示所有设备 ens33: flags4163<UP,BROADCAST,RUNNING,MUL…

RK3588+FPGA+算能BM1684X:高性能AI边缘计算盒子,应用于视频分析、图像视觉等

搭载RK3588&#xff08;四核 A76四核 A55&#xff09;&#xff0c;CPU主频高达 2.4GHz &#xff0c;提供1MB L2 Cache 和 3MB L3 &#xff0c;Cache提供更强的 CPU运算能力&#xff0c;具备6T AI算力&#xff0c;可扩展至38T算力。 产品规格 系统主控CPURK3588&#xff0c;四核…

数字、钱工具栏

/*** 提取字符串中的 数字 带小数点 &#xff0c;没有就返回"0"** param money* return*/fun getMoney(money: String): String {var money moneyvar pattern Pattern.compile("(\\d\\.\\d)")var m pattern.matcher(money)if (m.find()) {money if (m.…

数据挖掘实战-基于长短期记忆网络(LSTM)的黄金价格预测模型 | 97% 准确度

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

攻防世界babyRE做法(Linux调试)

在做题之前我们先了解一些知识点&#xff0c;首先是汇编中的知识点&#xff0c;汇编中&#xff0c;数据和代码可以说是一回事&#xff0c;数据和代码可以无条件相互转换&#xff0c;换句话说&#xff0c;数据就是代码&#xff0c;代码就是数据 接下来开始做题&#xff0c;简单…

【经验总结】怎样查看计算机CPU核数量

方法一&#xff1a;任务管理器 方法二&#xff1a;设备管理器 选中“计算机”右击&#xff0c;选择“属性”&#xff1a; 选择“设备管理器”->“处理器”&#xff0c;有几行就代表有几个核&#xff1a;

Ubuntu系统升级k8s节点的node节点遇到的问题

从1.23版本升级到1.28版本 node节点的是Ubuntu系统20.04的版本 Q1 node节点版本1.23升级1.28失败 解决办法&#xff1a; # 改为阿里云镜像 vim /etc/apt/sources.list.d/kubernetes.list# 新增 deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main# 执…

浙江大爱遮阳新材料股份有限公司新品发布会圆满成功

5月29日,浙江大爱遮阳新材料股份有限公司新品发布会在上海国家会展中心举办。本次会议出席的嘉宾有浙江大爱遮阳新材料股份有限公司总经理俞彬军,常务副总王志华,上海大爱益可美遮阳科技有限公司总经理陆俊青,浙江大爱遮阳新材料股份有限公司销售经理平鸿烈,销售经理蒋扬锋和玛…