读流程
客户端接入后,下面一步操作就是读取客户端传输过来的数据,这一节我们就来分析下服务端读取客户端数据流程。从前面分析来看,channel
的事件轮询、事件处理是在NioEventLoop
的run
方法中,从这里我们就很容易找我服务端读流程的入口方法:processSelectedKeys()
。
(相关资料图)
从processSelectedKeys()
一直追踪下去,可以看到OP_READ
处理逻辑分支:
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { unsafe.read();}
可能你会比较奇怪:为什么OP_READ
和OP_ACCEPT
都会走这个分支?
OP_ACCEPT
是NioServerSocketChannel
处理的事件,而OP_READ
是NioSocketChannel
处理的事件,所以,虽然它们都走这个分支,但是channel类型确是不一样的,即这里的unsafe
类型也不一样,一个是:NioMessageUnsafe
,另一个是:NioSocketChannelUnsafe
。NioServerSocketChannel
负责监听客户端连接,当有客户端连接进入时,对它来说就是有个读入消息需要被处理。这里我们是处理client channle
的OP_READ
,所以,unsafe
是NioSocketChannelUnsafe
类型实例。
AbstractNioByteChannel.NioByteUnsafe#read
方法代码如下:
public final void read() { final ChannelConfig config = config(); if (shouldBreakReadReady(config)) { clearReadPending(); return; } final ChannelPipeline pipeline = pipeline(); final ByteBufAllocator allocator = config.getAllocator(); final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle(); allocHandle.reset(config); ByteBuf byteBuf = null; boolean close = false; try { do { // 申请ByteBuf对象 byteBuf = allocHandle.allocate(allocator); //doReadBytes(byteBuf):将数据读取到ByteBuf中 //lastBytesRead()将读取的字节数设置到lastBytesRead allocHandle.lastBytesRead(doReadBytes(byteBuf)); if (allocHandle.lastBytesRead() <= 0) { byteBuf.release(); byteBuf = null; close = allocHandle.lastBytesRead() < 0; if (close) { readPending = false; } break; } allocHandle.incMessagesRead(1); readPending = false; //触发pipeline channelRead事件,将读入数据ByteBuf传入到handler中 pipeline.fireChannelRead(byteBuf); byteBuf = null; } while (allocHandle.continueReading());//判断是否继续读取 allocHandle.readComplete(); //触发pipeline channelReadComplete pipeline.fireChannelReadComplete(); if (close) { closeOnRead(pipeline); } } catch (Throwable t) { handleReadException(pipeline, byteBuf, t, close, allocHandle); } finally { if (!readPending && !config.isAutoRead()) { removeReadOp(); } }}
这个方法刨除其它逻辑,关于客户端数据处理逻辑主要包括3个步骤:
allocHandle.lastBytesRead(doReadBytes(byteBuf))
:调用java api
,从channel
中读取字节数据到ByteBuf
缓存中;pipeline.fireChannelRead(byteBuf)
:触发pipeline
的channelRead
事件,并将带有读入数据的ByteBuf
通过参数传入;pipeline.fireChannelReadComplete()
:触发pipeline
的channelReadComplete
事件;事件传播
调用pipeline
的fireChannelRead()
就可触发channelRead
事件在handler
之间传播,事件传播这块代码比较绕,给人感觉不停的来回调用容易绕晕,下面通过图可以更加直观的看出调用流程,再配合代码就很好理解了。
关键点就在于HandlerContext
中提供了一个静态方法:invokeChannelRead(final AbstractChannelHandlerContext next, Object msg)
,第一个是在哪个handler
上触发事件,第二个参数就是数据本身,通过这个方法就可以指定在哪个handler
上触发channelRead
事件。由于pipeline
中的handler
是被包装成HandlerContext
放入的,所以,可以通过handler()
方法找到真正的handler
对象进行触发。
比如pipeline
的fireChannelRead()
就是触发head
的channelRead
事件,如果处理完成需要把事件继续传播给下一个handler
,就需要调用ctx.fireChannelRead(msg)
方法即可,该方法中通过next
属性获取到下一个节点,然后执行static invokeChannelRead(next, msg)
这个方法就可以将事件传播到下一个节点上。
pipeline.fireChannelRead(byteBuf)
运行完成后会调用pipeline.fireChannelReadComplete()
方法,触发channelReadComplete
事件,执行机制和channelRead
事件一样,就不再赘述。
搞清楚上面原理,就很容易理解
ctx.fireChannelRead()
和ctx.pipeline().fireChannelRead()
之间的区别了,避免误用。
Pipeline线程模型
上面分析的都是常规模式,没有给handler
指定额外线程情况下channelRead
和channelReadComplete
传播机制,大致如下图:
先触发channelRead
事件,按照pipeline
中顺序依次触发,当所有handler
都触发完后,再触发channelReadComplete
事件,按照pipeline
中的顺序依次触发。这些所有流程采用的都是同步方式,在同一个线程中执行,这个线程就是channel
注册的NioEventLoop
。
我们来看下static void invokeChannelRead()
这个方法:
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) { final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeChannelRead(m); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeChannelRead(m); } }); }}
在执行next.invokeChannelRead(m)
方法前有个executor.inEventLoop()
判断,判断当前执行线程是不是就是handler
执行所需的线程。执行handler
方法是不能随便线程都可以去执行的,必须使用handler
内部指定的executor
线程执行器中执行才行。如下图,也就是说红色框框中的内容必须在executor
线程执行器中执行,如果当前线程和handler
执行线程不是同一个,就需要进行线程切换:则调用封装成一个任务,提交到executor
的任务队列中让其执行。
executor
线程执行器是通过next.executor()
方法获取到的,从这个方法源码中可以看到获取逻辑:如果HandlerContext
中executor
有值则直接返回;否则返回channel
注册的NioEventLoop
作为线程执行器。
在添加handler
时可以指定一个EventGroup
:pipeline.addLast( bizGroup, "handler2", new OtherTest02());
,这样,再把handler
包装成HandlerContext
过程中会从这个EventGroup
根据chooser
选取策略获得一个EventLoop
赋值给executor
。
所以,从上面分析,默认情况下handler
都是在channel
注册的NioEventLoop
线程中执行的,除非在addLast
添加handloer
时特别指定。
下面我们通过一个案例分析下pipeline
线程模型,如下,给handler02
添加一个额外的线程池:
EventLoopGroup bizGroup = new NioEventLoopGroup(10, new ThreadFactoryBuilder().setNameFormat("biz-%s").build());protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast( "handler01", new OtherTest01()); pipeline.addLast( bizGroup, "handler02", new OtherTest02()); pipeline.addLast( "handler03", new OtherTest03());}
这时,channelRead
和channelReadComplete
事件触发流程见下图:
channelRead
事件执行流程说明:
handler01
的channelRead
事件,本身当前线程和handler01
是同一个线程,所以,直接调用handler#channelRead()
方法;handler01#channelRead()
方法执行完成后,事件继续向下传播,需要调用handler02#channelRead()
方法,但是handler02
执行线程并不是默认的channel
的注册线程,而是额外设置的biz
线程,需要将调用包装成一个任务提交到biz
线程的任务队列taskQueue
中,然后直接返回;biz线程执行器内部线程会一直循环从taskQueue
中获取任务执行,这样就完成了线程切换效果;当handler02#channelRead()
方法执行完成后,需要执行handler03#channelRead()
,它们又不在同一个线程中执行,这时有需要切换线程,所以会把handler03#channelRead()
的调用封装成一个任务提交到register eventLoop的taskQueue
中,待其内部线程提取执行;下面再来看下channelReadComplete
事件执行流程:
a1
将任务提交给taskQueue
任务队列后直接返回了,而不是等其执行完成再返回;a1
返回后,从源码分析来看,会立即触发channelReadComplete
事件,涉及到线程切换,同理b1
这里也是将handler02#channelReadComplete()
调用封装成任务放入到biz eventLoop
的taskQueue
中的,然后也直接返回了;这样,biz eventLoop
线程执行器taskQueue
中就有两个任务,会按照顺序依次执行:先执行channelRead()
调用,再执行channelReadComplete()
调用;执行a3、b3
时同理;总结
从上面可以看出,Pipeline
中handler
可以在不同线程间切换得到关键是:taskQueue
。还要一点非常重要:handler
线程池执行器默认使用的channel
注册的NioEventLoop
这个,NioEventLoop
采用的是单线程工作模式,同时还需要处理selector.select()
事件轮询,所以,handler
里肯定不能有耗时、特别是IO
阻塞等操作,不然卡在handler
中,selector#select()
执行不到,无法及时接收到客户端传送过来的数据。
下一篇:最后一页
X 关闭
推荐内容
- 【Netty源码分析】04 服务端读流程
- 真假学园第二季03_真假学园第三季剧情
- 荀子拼音版原文朗读_荀子拼音
- 碳酸锂“真相”:远期合约低至17.3万元!TOP10标配的这一业务将受重创! 环球快看
- 美议员:应着眼全局推动数据安全立法 而不是把TikTok当替罪羊
- 3月27日国内现货锡市场价格上涨
- 每日热门:狗仔公开爆料刘宇宁有过婚史,网友直呼不意外,还被扒出改过年龄
- 特斯拉推出车贴拉花,适用于Model 3/Y车型
- 股票涨速超过多少是好?正常股票和ST股涨幅有什么区别?
- 退市的股票怎么处理-世界消息
- 天津多举措推进重点群体创业
- 看点:女生靠摆地摊还清百万负债 还有人两周赚1万5、月入万元:摆摊真这么赚钱?
- 速看:权益基金经理管“固收+” 市场敏锐度是关键优势
- 天天时讯:前2月内蒙古主要能源产品产量居全国前列
- 求答案一老人钓鱼图有14个字_求答案
- 世界微动态丨腾讯云边缘安全加速(EdgeOne)之规则引擎
- 移动短信查话费查询(移动短信查话费)
- 演员周扬个人资料 快播
- 环球快资讯:发改委主任郑栅洁:我国将防范化解金融和房地产等领域风险
- 习近平向中国发展高层论坛2023年年会致贺信
- 种植养殖培训内容_种养殖技术培训内容
- 用木头做的门是什么门
- 游戏驿站暴跌触发熔断 具体是什么情况目前情况如何-环球新消息
- 反复发热是什么问题_反复发热什么原因|当前独家
- 三无快艇”盗窃鳗鱼苗案件高发频发,上海奉贤海警局联合区农业农委开展清网执法行动
- 圣水是什么水|焦点消息
- 天天快看:生薏米可以直接泡水喝吗(生薏米)
- 头条焦点:杭州灵隐寺旁小溪中大量放生乌龟死亡上热搜,引发网友热议
- 英格兰银行简史_关于英格兰银行简史的简介
- 卸磨杀驴是什么意思-全球看热讯
- 一般的房拆迁如何补偿? 快播
- 首架,正式交付!
- 最新3月24日铝业废铝价格行情汇总-每日精选
- 新动态:39.9/3瓶!懒人必备洁面慕斯,用过就不想再换!
- 世界速讯:LVJI TECH(01745)发布年度业绩 股东应占溢利3753.7万元 同比扭亏为盈
- 古代女生穿裙子里面穿啥|世界简讯
- 每日看点!欧美男女性交
- 周燕飞到湘西州幼儿园督导检查食品安全工作 每日简讯
- 临港集团上海临港现代物流经济发展有限公司总经理助理阮海一教授等多家单位领导到访上海市仓储与配送行业协会
- 洗米水洗脸有好处吗_洗米水洗脸有什么好处
- 世界讯息:六种制式一网打尽 《龙与地下城:侠盗荣耀》预售开启
- 墙布选什么颜色显大气
- 2023全球6G技术大会 “超级基础设施”赋能全社会数字化转型 全球快播报
- 保山市建立代表委员意见建议回复工作机制
- 世界热资讯!新增企业600家 加快点亮“满天星” 西部(重庆)科学城核心区今年力争实现软件产业收入180亿元
- 速讯:2019年华语娱乐圈内的人生赢家,不是肖战,不是李现,而是他
- SpringBoot整合ElasticSearch-世界速讯
- 2022年农历三月廿三祭祀吉日 2022年农历三月廿三宜祭祀吗
- 当前热文:兴业银行03月23日获沪股通增持114.59万股
- 全球球精选!替硝唑功效_替硝唑片的功效
- 环球今日报丨郑州市第一〇二高级中学召开班主任工作会议
- 明确!昆明主城区2023年首期住宅维修资金交存标准来了-世界百事通
- 陈梦克星入选冠军赛,王曼昱的两大对手,也入选了赛事阵容 全球聚看点
- 全球看热讯:眼部彩妆步骤
- 天天微头条丨校园枪声再起!美国丹佛高中17岁学生开枪打伤两人
- 佛罗里达州报告了新的蚊子种类_焦点
- 每日热文:天行广告防火墙卸载不了怎么办-天行广告防火墙
- 突发!一艘俄罗斯货船在芬兰港口被扣留
- 2023中国IC领袖峰会:Cadence、安谋科技、紫光展锐、芯原、思特威等企业领袖已加入,欢迎围观!
- 哈空调:公司的空冷设备不能用在数据中心机房
- 乐次元和乐视超级会员区别_全球时快讯
- 凯利泰:3月22日融资买入323.05万元,融资融券余额3.89亿元 天天快播报
- 热资讯!在甘肃种一颗牙多少钱?3850元,纳入医保
- 英国下议院投票通过“斯托蒙特刹车机制” 全球通讯
- 快看:五连败!CBA劲旅颜面尽失,创1大窝囊纪录,高诗岩怒摔直接离场!
- 【天天播资讯】一箭四星!“重庆造”天目一号掩星星座03-06星成功发射
- 打call是什么意思-全球报道
- 世界播报:美国对德国实施去工业化,中国捡落地桃子
- 蒂尼倍斯特全屋定制多少钱_蒂尼倍斯特全屋定制
- 网络语fw是什么意思
- Mysteel日报:全国生铁价格主稳个调 全球播报
- 田忌赛马教学反思课后反思_田忌赛马教学反思 焦点报道
- 速讯:松花蛋怎么制作_松花皮蛋的制作方法
- 全球今亮点!提示的近义词_提示英文
- 山坝村村民委员会
- 华钰矿业03月21日获沪股通增持57.91万股
- 今日看点:茉莉花功效(茉莉花功效)
- 拉直板发黄怎么补救_拉直板发黄如何补救_焦点报道
- 李家超:香港金融体系稳健,瑞信事件对港无重大影响 全球观焦点
- 从春天出发 | 长春城市新景观:立体过街通道,让城市“脉动”更畅通
- 全红婵令人担心,陈芋汐有望翻盘,中国游泳2大名将相互鼓励 环球观点
- 贵南高铁与南宁枢纽站场全面完成接轨连通
- 读卡器怎么老是写保护_我的读卡器老是说被写保护,这是为什么啊该怎么解决
- 哈法亚现场的“女铁人”-天天百事通
- 【当前独家】福建省公立大专院校待遇_福建省公立大专院校
- soulmate是什么意思你知道不_soulmate是什么意思 环球最资讯
- 谷爱凌太狠了!时隔1年回到中国,直奔健身房,晒6块腹肌+好身材
- 甘泉县:打造育苗工作“升级版” 奏响春耕备耕“进行曲”
- qq在线客服人工电话_qq在线客服
- 2023年常州清明节祭扫专线|当前热文
- 今日要闻!中国工程科技论坛暨第二届世界大跨拱桥建造技术大会在南宁举行
- 速看:如何挑选好的山药 怎样选质量好的山药呢
- 今头条!山区土鸡放牧饲养技术
- 法媒:调查显示,近半受访女科学家曾遭性骚扰-天天最资讯
- 童年女神复出,她还在为我们造梦
- qq小冰猜明星答案大全猜码图_qq小冰猜明星
- 快消息!围攻“光明顶” | 合资淡季卖车,卖的都是品牌力
- 日本电影冲绳决战下载_日本冲绳旅游攻略-天天微速讯
- 让沈醉碰了软钉子的川岛芳子,当年戴笠用了什么招数,把她吓得全都招了? 头条
- “挑战杯”中国大学生创业计划竞赛全国决赛举行 463个项目进入终审答辩_当前热门
精彩推荐
-
【Netty源码分析】04 服务端读流程2023-03-27
-
真假学园第二季03_真假学园第三季剧情2023-03-27
-
荀子拼音版原文朗读_荀子拼音2023-03-27
-
碳酸锂“真相”:远期合约低至17.3万元!TOP10标配的这一业务将受重创! 环球快看2023-03-27
-
美议员:应着眼全局推动数据安全立法 而不是把TikTok当替罪羊2023-03-27
-
3月27日国内现货锡市场价格上涨2023-03-27
-
每日热门:狗仔公开爆料刘宇宁有过婚史,网友直呼不意外,还被扒出改过年龄2023-03-27
-
特斯拉推出车贴拉花,适用于Model 3/Y车型2023-03-27
-
股票涨速超过多少是好?正常股票和ST股涨幅有什么区别?2023-03-27
-
退市的股票怎么处理-世界消息2023-03-27
-
天津多举措推进重点群体创业2023-03-27
-
看点:女生靠摆地摊还清百万负债 还有人两周赚1万5、月入万元:摆摊真这么赚钱?2023-03-27
-
速看:权益基金经理管“固收+” 市场敏锐度是关键优势2023-03-27
-
天天时讯:前2月内蒙古主要能源产品产量居全国前列2023-03-26
-
求答案一老人钓鱼图有14个字_求答案2023-03-26
-
世界微动态丨腾讯云边缘安全加速(EdgeOne)之规则引擎2023-03-26
-
移动短信查话费查询(移动短信查话费)2023-03-26
-
演员周扬个人资料 快播2023-03-26
-
环球快资讯:发改委主任郑栅洁:我国将防范化解金融和房地产等领域风险2023-03-26
-
习近平向中国发展高层论坛2023年年会致贺信2023-03-26
-
种植养殖培训内容_种养殖技术培训内容2023-03-26
-
用木头做的门是什么门2023-03-26
-
游戏驿站暴跌触发熔断 具体是什么情况目前情况如何-环球新消息2023-03-26
-
反复发热是什么问题_反复发热什么原因|当前独家2023-03-26
-
三无快艇”盗窃鳗鱼苗案件高发频发,上海奉贤海警局联合区农业农委开展清网执法行动2023-03-25
-
圣水是什么水|焦点消息2023-03-25
-
天天快看:生薏米可以直接泡水喝吗(生薏米)2023-03-25
-
头条焦点:杭州灵隐寺旁小溪中大量放生乌龟死亡上热搜,引发网友热议2023-03-25
-
英格兰银行简史_关于英格兰银行简史的简介2023-03-25
-
卸磨杀驴是什么意思-全球看热讯2023-03-25
-
一般的房拆迁如何补偿? 快播2023-03-25
-
首架,正式交付!2023-03-25
-
最新3月24日铝业废铝价格行情汇总-每日精选2023-03-25
-
新动态:39.9/3瓶!懒人必备洁面慕斯,用过就不想再换!2023-03-25
-
古代女生穿裙子里面穿啥|世界简讯2023-03-24
-
每日看点!欧美男女性交2023-03-24
-
周燕飞到湘西州幼儿园督导检查食品安全工作 每日简讯2023-03-24
-
洗米水洗脸有好处吗_洗米水洗脸有什么好处2023-03-24
-
世界讯息:六种制式一网打尽 《龙与地下城:侠盗荣耀》预售开启2023-03-24
-
墙布选什么颜色显大气2023-03-24
-
2023全球6G技术大会 “超级基础设施”赋能全社会数字化转型 全球快播报2023-03-24
-
保山市建立代表委员意见建议回复工作机制2023-03-24
-
速讯:2019年华语娱乐圈内的人生赢家,不是肖战,不是李现,而是他2023-03-24
-
SpringBoot整合ElasticSearch-世界速讯2023-03-24
-
2022年农历三月廿三祭祀吉日 2022年农历三月廿三宜祭祀吗2023-03-24
-
当前热文:兴业银行03月23日获沪股通增持114.59万股2023-03-24
-
全球球精选!替硝唑功效_替硝唑片的功效2023-03-24
-
环球今日报丨郑州市第一〇二高级中学召开班主任工作会议2023-03-23
-
明确!昆明主城区2023年首期住宅维修资金交存标准来了-世界百事通2023-03-23
-
陈梦克星入选冠军赛,王曼昱的两大对手,也入选了赛事阵容 全球聚看点2023-03-23
-
全球看热讯:眼部彩妆步骤2023-03-23
-
天天微头条丨校园枪声再起!美国丹佛高中17岁学生开枪打伤两人2023-03-23
-
佛罗里达州报告了新的蚊子种类_焦点2023-03-23
-
每日热文:天行广告防火墙卸载不了怎么办-天行广告防火墙2023-03-23
-
突发!一艘俄罗斯货船在芬兰港口被扣留2023-03-23
-
哈空调:公司的空冷设备不能用在数据中心机房2023-03-23
-
乐次元和乐视超级会员区别_全球时快讯2023-03-23
-
凯利泰:3月22日融资买入323.05万元,融资融券余额3.89亿元 天天快播报2023-03-23
-
热资讯!在甘肃种一颗牙多少钱?3850元,纳入医保2023-03-23
-
英国下议院投票通过“斯托蒙特刹车机制” 全球通讯2023-03-23
-
快看:五连败!CBA劲旅颜面尽失,创1大窝囊纪录,高诗岩怒摔直接离场!2023-03-23
-
【天天播资讯】一箭四星!“重庆造”天目一号掩星星座03-06星成功发射2023-03-22
-
打call是什么意思-全球报道2023-03-22
-
世界播报:美国对德国实施去工业化,中国捡落地桃子2023-03-22
-
蒂尼倍斯特全屋定制多少钱_蒂尼倍斯特全屋定制2023-03-22
-
网络语fw是什么意思2023-03-22
-
Mysteel日报:全国生铁价格主稳个调 全球播报2023-03-22
-
田忌赛马教学反思课后反思_田忌赛马教学反思 焦点报道2023-03-22
-
速讯:松花蛋怎么制作_松花皮蛋的制作方法2023-03-22
-
全球今亮点!提示的近义词_提示英文2023-03-22
-
山坝村村民委员会2023-03-22
-
华钰矿业03月21日获沪股通增持57.91万股2023-03-22
-
今日看点:茉莉花功效(茉莉花功效)2023-03-22
-
拉直板发黄怎么补救_拉直板发黄如何补救_焦点报道2023-03-21
-
李家超:香港金融体系稳健,瑞信事件对港无重大影响 全球观焦点2023-03-21
-
从春天出发 | 长春城市新景观:立体过街通道,让城市“脉动”更畅通2023-03-21
-
全红婵令人担心,陈芋汐有望翻盘,中国游泳2大名将相互鼓励 环球观点2023-03-21
-
贵南高铁与南宁枢纽站场全面完成接轨连通2023-03-21
-
读卡器怎么老是写保护_我的读卡器老是说被写保护,这是为什么啊该怎么解决2023-03-21
-
哈法亚现场的“女铁人”-天天百事通2023-03-21
-
【当前独家】福建省公立大专院校待遇_福建省公立大专院校2023-03-21
-
soulmate是什么意思你知道不_soulmate是什么意思 环球最资讯2023-03-21
-
谷爱凌太狠了!时隔1年回到中国,直奔健身房,晒6块腹肌+好身材2023-03-20
-
甘泉县:打造育苗工作“升级版” 奏响春耕备耕“进行曲”2023-03-20
-
qq在线客服人工电话_qq在线客服2023-03-20
-
2023年常州清明节祭扫专线|当前热文2023-03-20
-
今日要闻!中国工程科技论坛暨第二届世界大跨拱桥建造技术大会在南宁举行2023-03-20
-
速看:如何挑选好的山药 怎样选质量好的山药呢2023-03-20
-
今头条!山区土鸡放牧饲养技术2023-03-20
-
法媒:调查显示,近半受访女科学家曾遭性骚扰-天天最资讯2023-03-20
-
童年女神复出,她还在为我们造梦2023-03-20
-
qq小冰猜明星答案大全猜码图_qq小冰猜明星2023-03-19
-
快消息!围攻“光明顶” | 合资淡季卖车,卖的都是品牌力2023-03-19
-
日本电影冲绳决战下载_日本冲绳旅游攻略-天天微速讯2023-03-19
-
让沈醉碰了软钉子的川岛芳子,当年戴笠用了什么招数,把她吓得全都招了? 头条2023-03-19
-
“挑战杯”中国大学生创业计划竞赛全国决赛举行 463个项目进入终审答辩_当前热门2023-03-19