LWIP中socket是阻塞模式,如何在NIOS II中实现非阻塞模式的socket,通过fcntl等改变socket模式无法实现,可以采用多线程和定时器相结合的方式实现非阻塞模式的accept。
1)创建线程(任务),一个是主任务,另外一个是accept等待的任务(里面只有一个accept函数的循环运行)。
2)建立定时器中断,定时间隔自己选择,并编写中断服务程序。
3)accept函数返回的socket号以全局变量形式定义,方便两个任务间的通信连接。
4)运行时在需要等待连接处,开启定时器,并将主任务挂起,accept等待任务恢复,在定时时间内等待网络连接,定时时间到执行中断服务程序,挂起accept等待任务,恢复主任务,根据accept的返回值fd_visitor来判断是否有网络连接,如果fd_visitor值大于0,则说明有网络连接,建立网络连接,否则没有。
5)这样程序不会死在accept处,持续等待网络连接,而是等待一段时间后继续执行其他任务。
程序附录:
1)定时器中断服务程序:
void hand_timer1_interrupt()
{
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE,0);
if(timer_cnt0 < 5000) //5s执行一次查询
timer_cnt0++;
else
{
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_1_BASE,10);//关闭定时器
timer_cnt0=0;
printf("timer over\n");
OSTaskSuspend(SD_PIRO);
OSTaskResume(INNET_PIRO);
}
}
2)主线程部分程序
fd_listen=socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(TCP_PORT);
addr.sin_addr.s_addr = inet_addr(ip); //设定系统的IP
bind(fd_listen,(struct sockaddr *)&addr,sizeof(addr));
listen(fd_listen,5);
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_1_BASE,7);
OSTaskSuspend(INNET_PIRO);
OSTaskResume(SD_PIRO);
3)accept等待任务
void Task_wait()
{
while(1)
{
fd_visitor=accept(fd_listen,(structsockaddr*)&addr_rec,&sock_len);
}
}