这几天为了实现一个基于UDP的上层SIP协议,碰到一个离奇的问题,debug两天方得结果,太难受了。
问题描述:UDP客户端第一次通过sendto()发送消息给服务器端后,阻塞在recvfrom(),等待服务器返回消息。之后的第二次,第三次,第N次客户端都不会阻塞在recvfrom()函数,而是直接获得数据,不管服务器端有没有sendto(),而且每次获得的数据都是一样的。
问题根源:服务器端的recvfrom()函数的第四个参数一般情况下设置为 0,而客户端recvfrom()的第四个参数设置为 MSG_PEEK。查资料发现MSG_PEEK的意义:如果我们想要查看数据,又想数据仍然留在接收队列中以供本进程其他部分稍后读取,那么可以使用MSG_PEEK标志。
另外:
客户端通过调用sendto()函数来指名服务器的IP和端口,通过调用recvfrom()函数获得服务器的消息(因为服务器调用recvfrom()可以得到源客户端的地址和端口号然后在以这个地址和端口发送新的消息给客户端)。但是,如果必须要指名客户端的哪个端口来发消息,怎么办?这时可以bind一个端口给客户端,一切OK,当然很少有这样的需求。