做网站建设销售,东营企业网站seo,wordpress被和谐,排名前十的网页游戏一。进程处理多路IO请求
在没有多路复用IO之前#xff0c;对于多路IO请求#xff0c;一般只有阻塞与非阻塞IO两种方式
1.1 阻塞IO
需要结合多进程/多线程#xff0c;每个进程/线程处理一路IO 缺点#xff1a;客户端越多#xff0c;需要创建的进程/线程越多#xff0c…一。进程处理多路IO请求
在没有多路复用IO之前对于多路IO请求一般只有阻塞与非阻塞IO两种方式
1.1 阻塞IO
需要结合多进程/多线程每个进程/线程处理一路IO 缺点客户端越多需要创建的进程/线程越多相对占用内存资源较多
1.2 非阻塞IO
单进程可以处理但是需要不断检测客户端是否发出IO请求需要不断占用cpu消耗 cpu 资源
二.多路复用IO简介
本质上就是通过复用一个进程来处理多个IO请求基本思想由内核来监控多个文件描述符是否可以进行I/O操作如果有就绪的文件描述符将结果告知给用户进程则用户进程在进行相应的I/O操作 类似于下图的老师检查学生作业
三.多路复用I/O方案
目前在Linux系统有三种多路复用I/O的方案
select方案poll方案epoll方案
四.select 方案
4.1 设计思想
通过单进程创建一个文件描述符集合将需要监控的文件描述符添加到这个集合中由内核负责监控文件描述符是否可以进行读写一旦可以读写则通知相应的进程进行相应的I/O操作
4.2 实现方式
select多路复用I/O在实现时主要是以调用 select 函数来实现
select 函数
函数头文件
#include sys/select.h函数原型
int select(int nfds, fd_set *readfds,fd_set*writefds,fd_set *exceptfds,struct timeval *timeout);函数功能
监控一组文件描述符阻塞当前进程由内核检测相应的文件描述符是否就绪,一旦有文件描述符就绪将就绪的文件描述符拷贝给进程唤醒进程处理函数参数
nfds:最大文件描述符加1
readfds:读文件描述符集合的指针
writefds:写文件描述符集合的指针
exceptfds:其他文件描述符集合的指针
timeout:超时时间结构体变量的指针函数返回值
成功:返回已经就绪的文件描述符的个数。如果设置timeout超时就会返回0
失败:-1并设置errno操作文件描述符集合函数
void FD_CLR(int fd,fd_set *set)
将fd从文件描述符集合中删除int FD_ISSET(int fd,fd_set *set)
判断fd是否在文件描述符集合中void FD_SET(int fd,fd_set *set)
将文件描述符添加到文件描述符集合中void FD_ZERO(fd_set *set)
将文件描述符集合清空参数描述:
fd:文件描述符
set:文件描述符集合的指针示例代码使用select函数监控有名管道如果有输入则打印相应的信息
write.cpp
using namespace std;
#includeiostream
#includestring
#include cstring
#includevector
#includedeque
#includecstdio
#includectime
#includedeque
#includecstdlib
#includepthread.h
#include unistd.h
#include sys/select.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#define PATH /home/linuxfu/pipo
int main(){int ret access(PATH,F_OK);if(ret -1){mkfifo(PATH,0644);}int fd open(PATH,O_WRONLY);if(fd -1){cout create failed endl;exit(EXIT_FAILURE);} char buf[128] { 0 };while(1){memset(buf,0,sizeof(buf));cout 请输入你想要输入的字符串:;fgets(buf,sizeof(buf) - 1,stdin);buf[strlen(buf) - 1] \0;ssize_t wtypes write(fd,buf,size(buf));if(wtypes -1){cout write failed endl;close(fd);exit(EXIT_FAILURE); }}close(fd);return 0;
}select.cpp
using namespace std;
#includeiostream
#includestring
#includevector
#includedeque
#includectime
#includedeque
#includecstdlib
#includepthread.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include sys/select.h
#define PATH /home/linuxfu/pipo
int main(){int ret access(PATH,F_OK);if(ret -1){mkfifo(PATH,0644);}int fd open(PATH,O_RDONLY);if(fd -1){cout create failed endl;exit(EXIT_FAILURE);}fd_set rfds;FD_ZERO(rfds);FD_SET(0,rfds);FD_SET(fd,rfds);struct timeval tv;tv.tv_sec 5;tv.tv_usec 0;fd_set temp_rfds;//备份struct timeval temp_tv;//备份while(1){temp_rfds rfds;temp_tv tv;int ret select(fd 1,temp_rfds,NULL,NULL,temp_tv);if(ret -1){perror(ret);}else if(ret 0){cout time out endl;}else{for(int i 0;i ret;i){if(FD_ISSET(0,temp_rfds)){string temp;cin temp;cout temp endl;}if(FD_ISSET(fd,temp_rfds)){char buf[128] { 0 };ssize_t rtype read(fd,buf,size(buf));if(rtype 0){printf(content:%s,buf);}}}}}}答案图片 注意点:
struct timeval结构体
struct timeval {
__kernel_old_time_t tv_sec; /* seconds *///秒数
__kernel_suseconds_t tv_usec; /* microseconds *///毫秒数
};2.select 函数理解 3.超时时间的说明
如果timeout之后文件描述符集合中没有任何就绪的文件描述符select函数就会返回0超时之后timeout会被select函数修改表示超时时间已经使用完。如果想继续使用超时时间需要备份之前的struct timeval超时之后表示没有就绪的文件描述符此时文件描述符集合被赋值为空 因此需要将之前的文件描述符集合进行备份。
4.3多路复用IO-select底层原理分析
文件描述符集合
typedef struct
{
/* XPG4.2 requires this member name. Otherwise avoid the name
from the global namespace. */
#ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)-fds_bits)
#else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)-__fds_bits)
#endif
} fd_set;数组的类型为 long int 类型在 64 位系统中 long int 的大小为 8 个字节
typedef long int __fd_mask;数组的大小为16 __FD_SETSIZE / __NFDBITS
#define __FD_SETSIZE 1024
#define __NFDBITS (8 * (int) sizeof (__fd_mask))文件描述符集合的数组最终在存储时使用了位图的方式来记录相应的文件描述符具体原理如下:
数组中没有直接存储文件描述符而是使用某一位来表示该文件描述符是否需要监控需要监控的文件描述符需要转成数组的某一个元素的某一位然后将对应的位设置为1,例如当 fd 60 的成员需要监控则需要将数组的第0个成员的第 [60] bit 设置为1当 fd 64时则需要将数组的第1个成员的第[0] bit 设置为1 从上面的文件描述符集合内存管理可以分析出select 最终只能存储1024个文件描述符
select 底层原理分析 一.在 select() 函数中一共需要使用三个文件描述符集合,分别是1.in : 读文件描述符集合,主要包含 需要进行读的文件描述符的集合反映在底层实际可以从设备中读取数据2.out : 写文件描述符集合,主要包含 需要进行写的文件描述符的集合反映在底层实际可以将数据写入到设备中3.exp : 其他文件描述符集合,主要包含其他类型的操作的文件描述符集合二.调用了select() 函数,内核做了如下事情:1.从用户空间将集合的文件描述符拷贝到内核空间2.循环遍历 fd_set 中所有的文件描述符来检测是否有文件描述符可进行I/O操作(1)如果有文件描述符可进行I/O操作则设置返回的文件描述符集对应位1(res_in,res_out,res_exp)跳出循环直接返回。最终会赋值给 in,out,exp 文件描述符集合(2)如果没有文件描述符可进行I/O操作则继续循环检测。如果设置 timeout 则在超时后返回此时select() 函数返回0三.select() 函数减少了多进程/多线程的开销但仍然有很多缺点:1.每次调用select()函数都需要将fd集合拷贝到内核空间这个开销在fd很多时就越大2.每次都需要遍历所有的文件描述符集合这个开销在fd很多时就越大3.支持的文件描述符只有1024五.poll 方案
5.1 基本原理
多路复用poll的方式与select多路复用原理类似但有很多地方不同下面是具体的对比 在应用层是以结构体struct pollfd数组的形式来进行管理文件描述符在内核中基于链表对数组进行扩展select方式以集合的形式管理文件描述符且最大支持1024个文件描述 poll将请求与就绪事件通过结构体进行分开 select将请求与就绪文件描述符存储在同一个集合中导致每次都需要进行重新赋值才能进行下一次的监控 在内核中仍然使用的是轮询的方式与 select 相同当文件描述符越来越多时,则会影响效率
5.2 poll 方案
poll多路复用实现主要调用 poll 函数
函数头文件
#include poll.h函数原型
int poll(struct pollfd *fds, nfds_t nfds, int timeout);函数功能
监控多个文件描述符的变化函数参数
fds:sturct pollfd结构体指针
nfds:fds结构体的数量
timeout:超时时间,单位为ms函数返回值
成功:大于0返回就绪的文件描述符数量0超时返回没有文件描述符就绪
失败:-1,并设置errno参数相关说明
struct pollfd 结构体说明
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};nfds_t 类型定义
typedef unsigned long int nfds_t;poll 事件说明 示例代码使用poll函数监控有名管道如果有输入则获取标准输入的内容并打印
write.cpp
using namespace std;
#includeiostream
#includestring
#include cstring
#includevector
#includedeque
#includecstdio
#includectime
#includedeque
#includecstdlib
#includepthread.h
#include unistd.h
#include sys/select.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#define PATH /home/linuxfu/pipo
int main(){int ret access(PATH,F_OK);if(ret -1){mkfifo(PATH,0644);}int fd open(PATH,O_WRONLY);if(fd -1){cout create failed endl;exit(EXIT_FAILURE);} char buf[128] { 0 };while(1){memset(buf,0,sizeof(buf));cout 请输入你想要输入的字符串:;fgets(buf,sizeof(buf) - 1,stdin);buf[strlen(buf) - 1] \0;ssize_t wtypes write(fd,buf,size(buf));if(wtypes -1){cout write failed endl;close(fd);exit(EXIT_FAILURE); }}close(fd);return 0;
}poll.cpp
using namespace std;
#includeiostream
#includestring
#include cstring
#includevector
#includedeque
#includecstdio
#includectime
#includedeque
#includecstdlib
#includepthread.h
#include unistd.h
#include poll.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#define PATH /home/linuxfu/pipo
int main(){int ret access(PATH,F_OK);if(ret -1){mkfifo(PATH,0644);}int rfd open(PATH,O_RDONLY);if(rfd -1){cout create failed endl;exit(EXIT_FAILURE);} struct pollfd fds[2] { 0 };fds[0].fd 0;fds[0].events POLLIN;fds[1].fd rfd;fds[1].events POLLIN;while(1){int ret poll(fds,2,5000);if(ret -1){perror(ret);}else if(ret 0){cout time out endl;}else{for(int i 0;i 2;i){if(fds[0].revents POLLIN){char buf[128] { 0 };fgets(buf,sizeof(buf) - 1,stdin);buf[strlen(buf) - 1] \0;cout buf: buf endl;} if(fds[1].revents POLLIN){char buf[128] { 0 };ssize_t wtypes read(rfd,buf,sizeof(buf));if(wtypes 0){cout 字符串 buf endl;}}}}}close(rfd);return 0;
}6.epoll 方案
6.1epoll 基本原理
epoll相对于select与poll有较大的不同主要是针对前面两种多路复用 IO 接口的不足 select/poll的不足:
select 方案使用数组存储文件描述符最大支持1024个select 每次调用都需要将文件描述符集合拷贝到内核中非常消耗资源poll 方案解决文件描述符存储数量限制问题但其他问题没有得到解决select / poll 底层使用轮询的方式检测文件描述符是否就绪文件描述符越多则效率越低
**epoll优点
(1) epoll底层使用红黑树没有文件描述符数量的限制并且可以动态增加与删除节点不用重复拷贝 (2)epoll底层使用callback机制没有采用遍历所有描述符的方式效率较高** 6.2 select/poll 方案图解 6.3 epoll 方案图解 6.4epoll 创建
1.epoll创建需要调用epoll_create函数,用于创建epoll实例
函数头文件
#include sys/epoll.h函数原型
int epoll_create(int size);函数描述
epoll_create() creates a new epoll(7) instance. Since Linux 2.6.8, the size argument is ignored, but must be greater than zero;函数功能
创建一个epoll实例,分配相关的数据结构空间函数参数
size:需要填一个大于0的数从Linux 2.6.8开始size参数被忽略函数返回值
成功:返回epoll文件描述符
失败:返回-1,并设置errno示例代码创建一个epoll 实例
#include stdio.h
#include stdlib.h
#include string.h
#include sys/epoll.h
int main()
{
int epfd epoll_create(1);
if(epfd -1)
{
perror(epoll_create);
exit(EXIT_FAILURE);
}
printf(epfd%d\n,epfd);
return 0;
}epoll 函数控制 epoll控制函数主要用于文件描述符集合的管理包括增加、修改、删除等操作。 epoll_ctl函数详细信息如下
函数头文件
#include sys/epoll.h函数原型
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);函数参数
epfd:epoll 实例
op:epoll 操作命令字EPOLL_CTL_ADD:在epoll实例中添加新的文件描述符(相当于向红黑树中添加节点),并将事件与fd关联EPOLL_CTL_MOD:更改与目标文件描述符fd相关联的事件EPOLL_CTL_DEL:从epoll实例中删除目标文件描述符fd ,事件参数被忽略在系统中定义如下:
#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */
#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface.
*/
#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure.
*/
fd:操作的文件描述符
event:struct epoll_event结构体对象指针struct epoll_event 结构体定义如下:
ypedef union epoll_data {void *ptr;int fd;uint32_t u32;uint64_t u64;
} epoll_data_t;
struct epoll_event {uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */
};events : epoll事件事件具体定义如下:
enum EPOLL_EVENTS
{
EPOLLIN 0x001, // 读事件有效(非常常用)
#define EPOLLIN EPOLLIN
EPOLLPRI 0x002,
#define EPOLLPRI EPOLLPRI
EPOLLOUT 0x004, // 写事件有效(非常常用)
#define EPOLLOUT EPOLLOUT
EPOLLRDNORM 0x040,
#define EPOLLRDNORM EPOLLRDNORM
EPOLLRDBAND 0x080,
#define EPOLLRDBAND EPOLLRDBAND
EPOLLWRNORM 0x100,
#define EPOLLWRNORM EPOLLWRNORM
EPOLLWRBAND 0x200,
#define EPOLLWRBAND EPOLLWRBAND
EPOLLMSG 0x400,
#define EPOLLMSG EPOLLMSG
EPOLLERR 0x008,
#define EPOLLERR EPOLLERR
EPOLLHUP 0x010,
#define EPOLLHUP EPOLLHUP
EPOLLRDHUP 0x2000,
#define EPOLLRDHUP EPOLLRDHUP
EPOLLEXCLUSIVE 1u 28,
#define EPOLLEXCLUSIVE EPOLLEXCLUSIVE
EPOLLWAKEUP 1u 29,
#define EPOLLWAKEUP EPOLLWAKEUP
EPOLLONESHOT 1u 30,
#define EPOLLONESHOT EPOLLONESHOT
EPOLLET 1u 31 // 将EPOLL设为边缘触发(Edge Triggered)模式
#define EPOLLET EPOLLET
};epoll_data是一个共用体主要使用 fd 成员用于存储文件描述符
epoll 等待事件发生(关联的文件描述符就绪)这里调epoll_wait 函数 epoll_wait 函数详细信息如下
函数头文件
#include sys/epoll.h函数原型
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);函数功能
等待文件描述符关联的事件发生函数参数
epfd:epoll实例对象
events:存储就绪集合的数组的地址
maxevents:就绪集合的最大值
timeout:超时时间函数返回值
成功:返回就绪的文件描述符数量超时返回0
失败:返回-1,并设置errno6.5示例代码:
将有名管道描述符添加到epoll实例中等待用户输入数据如果没有则打印 timeout否则获取用户输入并输出。
write.cpp
using namespace std;
#includeiostream
#includestring
#include cstring
#includevector
#includedeque
#includecstdio
#includectime
#includedeque
#includecstdlib
#includepthread.h
#include unistd.h
#include sys/select.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#define PATH /home/linuxfu/pipo
int main(){int ret access(PATH,F_OK);if(ret -1){mkfifo(PATH,0644);}int fd open(PATH,O_WRONLY);if(fd -1){cout create failed endl;exit(EXIT_FAILURE);} char buf[128] { 0 };while(1){memset(buf,0,sizeof(buf));cout 请输入你想要输入的字符串:;fgets(buf,sizeof(buf) - 1,stdin);buf[strlen(buf) - 1] \0;ssize_t wtypes write(fd,buf,size(buf));if(wtypes -1){cout write failed endl;close(fd);exit(EXIT_FAILURE); }}close(fd);return 0;
}epoll.cpp
using namespace std;
#includeiostream
#includestring
#include cstring
#includevector
#includedeque
#includecstdio
#includectime
#includedeque
#includecstdlib
#includepthread.h
#include unistd.h
#include sys/epoll.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#define PATH /home/linuxfu/pipo
int main(){int ret access(PATH,F_OK);if(ret -1){mkfifo(PATH,0644);}int rfd open(PATH,O_RDONLY);if(rfd -1){cout create failed endl;exit(EXIT_FAILURE);} int epfd epoll_create(1);if( epfd -1){perror(epfd);exit(EXIT_FAILURE);}//将标准输入文件描述符添加到epoll中struct epoll_event ev;ev.events EPOLLIN;ev.data.fd rfd;int ret1 epoll_ctl(epfd,EPOLL_CTL_ADD,rfd,ev);if(ret1 -1){perror(ret1);exit(EXIT_FAILURE);}struct epoll_event ev1;ev1.events EPOLLIN;ev1.data.fd 0;int ret2 epoll_ctl(epfd,EPOLL_CTL_ADD,0,ev1);if(ret2 -1){perror(ret2);exit(EXIT_FAILURE);}struct epoll_event events[2];while(1){int res epoll_wait(epfd,events,2,4000);if(res -1){perror(res);}else if(res 0){printf(timeout\n);}else if(res 0){for(int i 0;i res;i){if(events[i].data.fd 0){char buf[128] { 0 };fgets(buf,sizeof(buf)-1,stdin);buf[strlen(buf) - 1] \0;cout buf: buf endl;}if(events[i].data.fd rfd){char buf[128] { 0 };ssize_t wtypes read(rfd,buf,sizeof(buf));if(wtypes 0){cout str: buf endl;}}}}}close(rfd);return 0;
}6.6 epoll 底层结构
文章转载自: http://www.morning.cjxqx.cn.gov.cn.cjxqx.cn http://www.morning.ggtgl.cn.gov.cn.ggtgl.cn http://www.morning.fhtbk.cn.gov.cn.fhtbk.cn http://www.morning.qfths.cn.gov.cn.qfths.cn http://www.morning.drkk.cn.gov.cn.drkk.cn http://www.morning.pxtgf.cn.gov.cn.pxtgf.cn http://www.morning.fddfn.cn.gov.cn.fddfn.cn http://www.morning.hhxwr.cn.gov.cn.hhxwr.cn http://www.morning.ljqd.cn.gov.cn.ljqd.cn http://www.morning.crtgd.cn.gov.cn.crtgd.cn http://www.morning.kwcnf.cn.gov.cn.kwcnf.cn http://www.morning.bxczt.cn.gov.cn.bxczt.cn http://www.morning.rqkzh.cn.gov.cn.rqkzh.cn http://www.morning.sjsks.cn.gov.cn.sjsks.cn http://www.morning.rcrnw.cn.gov.cn.rcrnw.cn http://www.morning.bpmtz.cn.gov.cn.bpmtz.cn http://www.morning.kdxzy.cn.gov.cn.kdxzy.cn http://www.morning.qbfqb.cn.gov.cn.qbfqb.cn http://www.morning.mspkz.cn.gov.cn.mspkz.cn http://www.morning.xirfr.cn.gov.cn.xirfr.cn http://www.morning.sftrt.cn.gov.cn.sftrt.cn http://www.morning.gxklx.cn.gov.cn.gxklx.cn http://www.morning.ljdtn.cn.gov.cn.ljdtn.cn http://www.morning.kkzwn.cn.gov.cn.kkzwn.cn http://www.morning.ptmsk.cn.gov.cn.ptmsk.cn http://www.morning.dnmzl.cn.gov.cn.dnmzl.cn http://www.morning.qgjwx.cn.gov.cn.qgjwx.cn http://www.morning.cjwkf.cn.gov.cn.cjwkf.cn http://www.morning.qstjr.cn.gov.cn.qstjr.cn http://www.morning.jhyfb.cn.gov.cn.jhyfb.cn http://www.morning.qfcnp.cn.gov.cn.qfcnp.cn http://www.morning.llcsd.cn.gov.cn.llcsd.cn http://www.morning.zckhn.cn.gov.cn.zckhn.cn http://www.morning.yhyqg.cn.gov.cn.yhyqg.cn http://www.morning.lkkkf.cn.gov.cn.lkkkf.cn http://www.morning.bkqdg.cn.gov.cn.bkqdg.cn http://www.morning.djpgc.cn.gov.cn.djpgc.cn http://www.morning.ympcj.cn.gov.cn.ympcj.cn http://www.morning.jydhl.cn.gov.cn.jydhl.cn http://www.morning.yqgny.cn.gov.cn.yqgny.cn http://www.morning.mdgb.cn.gov.cn.mdgb.cn http://www.morning.gfqjf.cn.gov.cn.gfqjf.cn http://www.morning.nxcgp.cn.gov.cn.nxcgp.cn http://www.morning.vtbtje.cn.gov.cn.vtbtje.cn http://www.morning.csznh.cn.gov.cn.csznh.cn http://www.morning.ypjjh.cn.gov.cn.ypjjh.cn http://www.morning.nqyfm.cn.gov.cn.nqyfm.cn http://www.morning.lbbgf.cn.gov.cn.lbbgf.cn http://www.morning.kgqpx.cn.gov.cn.kgqpx.cn http://www.morning.cpwmj.cn.gov.cn.cpwmj.cn http://www.morning.cfcdr.cn.gov.cn.cfcdr.cn http://www.morning.qhydkj.com.gov.cn.qhydkj.com http://www.morning.snmth.cn.gov.cn.snmth.cn http://www.morning.wztlr.cn.gov.cn.wztlr.cn http://www.morning.ldfcb.cn.gov.cn.ldfcb.cn http://www.morning.cwqln.cn.gov.cn.cwqln.cn http://www.morning.qfzjn.cn.gov.cn.qfzjn.cn http://www.morning.pxmyw.cn.gov.cn.pxmyw.cn http://www.morning.yqkxr.cn.gov.cn.yqkxr.cn http://www.morning.wdhhz.cn.gov.cn.wdhhz.cn http://www.morning.gtmdq.cn.gov.cn.gtmdq.cn http://www.morning.hlxxl.cn.gov.cn.hlxxl.cn http://www.morning.bgygx.cn.gov.cn.bgygx.cn http://www.morning.hjbrd.cn.gov.cn.hjbrd.cn http://www.morning.wjjsg.cn.gov.cn.wjjsg.cn http://www.morning.bmyrl.cn.gov.cn.bmyrl.cn http://www.morning.hhxwr.cn.gov.cn.hhxwr.cn http://www.morning.zsgbt.cn.gov.cn.zsgbt.cn http://www.morning.knnc.cn.gov.cn.knnc.cn http://www.morning.lzwfg.cn.gov.cn.lzwfg.cn http://www.morning.rbkdg.cn.gov.cn.rbkdg.cn http://www.morning.bpmns.cn.gov.cn.bpmns.cn http://www.morning.hmqwn.cn.gov.cn.hmqwn.cn http://www.morning.tsdjj.cn.gov.cn.tsdjj.cn http://www.morning.sftrt.cn.gov.cn.sftrt.cn http://www.morning.rmdwp.cn.gov.cn.rmdwp.cn http://www.morning.wknbc.cn.gov.cn.wknbc.cn http://www.morning.mypxm.com.gov.cn.mypxm.com http://www.morning.clqpj.cn.gov.cn.clqpj.cn http://www.morning.kbqqn.cn.gov.cn.kbqqn.cn