物联网LWIP开发6

D6并发服务器编程

6.1并发服务器(多线程)实现上

LWIP内部可以创建的socket的数量有限,必出通过一个宏开关进行配置,当一个新的客户端连接到并发服务器的时候,需要创建一个任务,一旦创建一个任务,每一个任务都要分配一个栈空间,越来越多的任务导致内存不够用

6.2并发服务器(多线程)实现下

6.3多路IO复用服务器模型

IO复用模型

selectAPI

标准select

int select(int nfds, fd_set *readfds, fd_set *writefds,
			fd_set *exceptfds, struct timeval *timeout);

//nfds: 	监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件描述符的状态
//readfds:	监控有读数据到达文件描述符集合,传入传出参数
//writefds:	监控写数据到达文件描述符集合,传入传出参数
//exceptfds:监控异常发生达文件描述符集合,如带外数据到达异常,传入传出参数
//timeout:	定时阻塞监控时间,3种情况
			//1.NULL,永远等下去
			//2.设置timeval,等待固定时间
			//3.设置timeval里时间均为0,检查描述字后立即返回,轮询
//return:	成功:所监听的所有监听集合中,满足条件的总数!
		  //失败:0 超时
		  //错误:-1
	struct timeval {
		long tv_sec; /* seconds */   秒
		long tv_usec; /* microseconds */  微秒
	};
	void FD_CLR(int fd, fd_set *set); 	//把文件描述符集合里fd清0
	int FD_ISSET(int fd, fd_set *set); 	//测试文件描述符集合里fd是否置1
	void FD_SET(int fd, fd_set *set); 	//把文件描述符集合里fd位置1
	void FD_ZERO(fd_set *set); 			//把文件描述符集合里所有位清0
/*
注意:
    1.	select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开的文件描述符个数并不能改变select监听文件个数
2.		解决1024以下客户端时使用select是很合适的,但如果链接客户端过多,select采用的是轮询模型,会大大降低服务器响应效率,不应在select上投入更多精力

 以前一个返回值,可以返回一个0或1,多个返回值返回的是参数,也就是用集合

LWIP select

/* FD_SET used for lwip_select */
#ifndef FD_SET
#undef  FD_SETSIZE
/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */
#define FD_SETSIZE    MEMP_NUM_NETCONN   // 默认4个栈
#define FDSETSAFESET(n, code) do { \
  if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \
  code; }} while(0)
#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\
  (code) : 0)
#define FD_SET(n, p)  FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |=  (1 << (((n)-LWIP_SOCKET_OFFSET) & 7)))
#define FD_CLR(n, p)  FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7)))
#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &   (1 << (((n)-LWIP_SOCKET_OFFSET) & 7)))
#define FD_ZERO(p)    memset((void*)(p), 0, sizeof(*(p)))
//fd_set
typedef struct fd_set
{
  unsigned char fd_bits [(FD_SETSIZE+7)/8];
} fd_set;
//MEMP_NUM_NETCONN
#if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__
#define MEMP_NUM_NETCONN                4
#endif
//LWIP_SOCKET_OFFSET
#if !defined LWIP_SOCKET_OFFSET || defined __DOXYGEN__
#define LWIP_SOCKET_OFFSET              0
#endi

select编程模型

位图:内存中的 一个字节的每一个 位 ,表示对应的一个状态,举个例子,有16个Led(标号 1~16) ,需要控制这些Led 亮灭的状态,如果用2个字节表示这些LED的状态,可以用第一个字节的bit0 表示 Led1的状态,用 bit1 表示 Led2 的状态,以此类推,用第二个字节的 bit 0 表示 Led9的状态,bit 1 表示 Led10 的状态。。。这里面,定义的 unsigned char 类型的 fd_bits[],数组中,每一个字符的每一个 bit 位,代表对应的 fd 有没有数据。

6.4并发服务器(select)实现上

在处理一个事件循环或IO多路复用(如使用select、poll、epoll等机制),"nready" 可能表示在当前检查周期内有多少个文件描述符(sockets、pipes等)已经准备好进行读、写或异常处理操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值