上篇文章说了下 udp 并发模型。然后笔者也自己编写了一套代码,基本上能显示 udp 并发机制。大致原理参考:
http://blog.csdn.net/aa120515692/article/details/47294335
select机制能很好地提供多路IO功能。对于本套代码,已基本上能提供类似 select 的功能
主要函数接口:
void listen_head_init(struct list_head *head)
初始化一个 链表头
int listen_add(struct list_head *head, listen_t *listen)
将要监听的 listen 添加到这个链表头
recv_from_listen_head
从链表中获取数据
示例:
//我们创建两个 listen_head
struct list_head poll_head_1, poll_head_2;
int main(int argc, char *argv[])
{
int poll_num = 0;
struct listen *_listen;
/* 初始化socket */
sockfd = init_socket();
/*
开始监听这个socket. 运行最大的连接数为10
该函数类似于TCP协议中的 int listen(SOCKET sockfd, int backlog)
*/
server_listen(&sockfd, 10);
/* 初始化这个poll 机制 */
listen_head_init(&poll_head_1);
listen_head_init(&poll_head_2);
while(1)
{
/* 获得一个连接。类似于TCP的
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
*/
_listen = server_accept();
if(_listen == NULL){
continue;
}
printf("new client \r\n");
if(poll_num < 5)
{
/* 前面五个连接者添加到 poll_head_1 */
poll_num ++;
listen_add(&poll_head_1, _listen);
}else{
/* 添加到 poll_head_2 */
poll_num ++;
listen_add(&poll_head_2, _listen);
}
}
}
然后我们就可以从中两个 listen_head 中读取数据了
while(1)
{
/*
从 poll_head_1 中读取数据。
此时,前面五个 listen 被挂钩到这个 poll_head_1,所以这五个listen中任何一个有了数据
recv_from_listen_head 都会返回,而且将 _listen 指向这个 listen
这样,我们就可以知道是哪个listen有数据了
*/
ret = recv_from_listen_head(poll_head_1, &_listen, (struct sockaddr *)&clientaddr, buf, 1204, -1);
if(ret == -1)
{
printf("%p recv is err \r\n", _listen);
}else{
printf("__ poll %p recv %d byte data is [%s]\r\n", _listen, ret, buf);
if((ret = sendto(sockfd, buf, ret, 0, (struct sockaddr *)(&(_listen->addr)),
sizeof(struct sockaddr))) == -1)
{
perror("sendto :");
}
printf("sento [%s]\r\n", buf);
}
}