关于recv、recvfrom的阻塞所遇到的问题(MSG_DONTWAIT)

近期,在做网络通信时,需要开发出一个应用程序来随时更改转发的目标地址,并同时要一直接收别的主机发来的命令从而进行一系列操作。由于之前没有做过windows系统下的窗口程序开发,我开始一点一点学习怎么创建窗口,当应用界面大概成功的时候,出现了一个问题。就是我需要不断地去询问要不要改地址,有没有接收到新的命令。然而当我觉得只要把两个功能放在同一个循环中就可以实现时,却发现,两种功能有种互斥的感觉。当接收消息时,窗口界面的消息便获取不到,无法更改目标地址,我想着获取消息的功能里也没有写循环,怎么就一直出不来了呢?甚至想着将接收功能设置为守护进程,从而实现并发的效果,奈何之前一直在学习Linux系统,转过来发现Windows系统的进程创建要麻烦很多,又实在不理解为什么逻辑感觉没问题,会一直卡在那。我继续寻找问题所在,最后终于发现是因为接收函数处于阻塞状态,就是接不到消息我就一直在那接收,导致程序进行不下去。找到问题了,开始尝试解决,找到recv或recvfrom函数,这两个函数都是接收函数,看一下函数原型:

recv(SOCKET s,char *buf,int len,int flags);

recvfrom(SOCKET s,char *buf,int len,int flags,struct sockaddr *from,int *fromlen);

当recvfrom函数的后两个参数为NULL时也就和recv一样啦。解释一下各个参数:

s:套接字描述符;

buf:接收数据的缓冲区;

len:接收多长的数据;

flags:操作方式标志;(该问题主要出在这里,所以详细说一下)

一般设置为0:默认阻塞状态;(我这种情况就不一般,不能为0)

MSG_DONTWAIT:本次操作设置为不阻塞;(正常把flags参数改为这项就可以了,但它还是不一般,后面详聊)

MSG_PEEK:只用于接收函数,表示接收消息后在消息队列中保留原数据,不刷新缓冲区,只是从缓冲区查数据而不是取走数据;

MSG_WAITALL:要求阻塞操作;

还有很多其他标志,可以自行搜索,这里不再过多赘述;

后面两个参数只存在在recvfrom中,一般用来回传信息,表示已经接收到数据,增强数据传递的可靠性:

from:指向源地址缓冲区;

fromlen:指向源地址缓冲区长度;

将recvfrom函数的第四个参数由0改为MSG_DONTWAIT设置成非阻塞状态,继续测试发现找不到声明;

找不到声明,那就到头文件里看一下是不是写错了导致找不到宏定义,进入winsock2.h文件中查看发现,还真就没有这个定义;

后来查询资料发现,Linux系统里定义了很多宏来方便调用,但windows却没有,不要着急,不用急着将两个系统融合,还可以对套接字进行非阻塞设置;

找到windows系统的套接字设置函数ioctlsocket,也封装在winsock2.h头文件中,函数原型如下:

ioctlsocket(SOCKET s,__LONG32 cmd,u_long *argp);

s:套接字描述符;

cmd:对套接口s的操作命令;

argp:指向cmd所带参数的指针;

其中cmd也是包含很多命令,在这里我们用到FIONBIO,它表示支持或禁止套接口的非阻塞模式;

当cmd为FIONBIO时,argp为0表示阻塞状态,argp为1表示非阻塞状态;

所以,我们这里在套接字创建后对其进行设置:

编译通过,问题解决,特此记录!

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值