udp编程问题

controstr 2009-07-30 10:57:33
使用udp编程,

m_hSocket = (int)::socket( AF_INET, SOCK_DGRAM, 0 );

bind();

unsigned long arg = 1;
if ( ioctlsocket(m_hSocket, FIONBIO, &arg) != 0 )
return false;
//.............

int nBufSize = 1024*8;
if ( setsockopt(m_hSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&nBufSize, sizeof(nBufSize)) == SOCKET_ERROR )
break;
if ( setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&nBufSize, sizeof(nBufSize)) == SOCKET_ERROR )
break;
if ( setsockopt(m_hSocket, SOL_SOCKET, TCP_NODELAY, (char*)&nBufSize, sizeof(nBufSize)) == SOCKET_ERROR )
break;


::sendto( m_hSocket, pBuf , 100, 0, (sockaddr*)&addr, sizeof(addr) ); // 这里成功发送


char pBuf[1024];
SOCKADDR_IN addr;
int nLen = sizeof(addr);
int bytes = ::recvfrom( m_hSocket, pBuf, 4, 0, (struct sockaddr*)&addr, &nLen );
// bytes 返回-1,但pBuf里有值,而且是sendto发过来的值,长度为4字节
// GetLastError 返回 10040


// 如果改用以下方式接收正常
int bytes = ::recvfrom( m_hSocket, pBuf, 100, 0, (struct sockaddr*)&addr, &nLen );
// bytes 返回实际接收字节长度


请问这个是什么问题引起的
...全文
175 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
controstr 2009-08-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 bylea 的回复:]
UDP,是已经消息块的形式发送的,是以块为单位进行接收的,当你的::recvfrom 给的可用缓冲区小于当前消息块时,UDP认为这个消息块无法完成传送,就会产生错误.

所以说::recvfrom 给的缓头冲区最好大些,通常说64KB就完全可以了(不关心内存的消耗的情况).


[/Quote]
这才回答了我提问题的核心

udp发送数据时要么成功,要么在网卡中就是一个完整的包,recvfrom时不管缓冲区有多大(必须大于发送的字节数,一般设置足够大)都只会接收一个包
newboy686 2009-08-06
  • 打赏
  • 举报
回复
晕, 有了错误代码还不知道怎么查!
wanjingwei 2009-08-02
  • 打赏
  • 举报
回复
顶下
Ghost226 2009-08-02
  • 打赏
  • 举报
回复
你的第一个recvfrom语句定义的是接受4个字节大小,sento发过来的数据长度当让为4,第二个定义的是100个字节,100大于你实际接受的字节数,它返回当然是实际接受的字节数
zyq1600356618 2009-08-01
  • 打赏
  • 举报
回复
顶 , 这个问题很简单
cattycat 2009-07-31
  • 打赏
  • 举报
回复
::sendto( m_hSocket, pBuf , 100, 0, (sockaddr*)&addr, sizeof(addr) ); // 这里成功发送

同意楼上,发送的是100字节啊,接收的缓冲只有4字节肯定会出错了。
Ghost90 2009-07-31
  • 打赏
  • 举报
回复
::sendto( m_hSocket, pBuf , 100, 0, (sockaddr*)&addr, sizeof(addr) ); // 这里成功发送
这里发的显然不是4字节呀

int bytes = ::recvfrom( m_hSocket, pBuf, 4, 0, (struct sockaddr*)&addr, &nLen );
// bytes 返回-1,但pBuf里有值,而且是sendto发过来的值,长度为4字节
// GetLastError 返回 10040

这里当然收不全了
controstr 2009-07-31
  • 打赏
  • 举报
回复
不知道是不是真这样
bylea 2009-07-31
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 controstr 的回复:]
会不会有像TCP一样,如果接收缓冲足够大,会不会每次接收二个包,比如sendto二次,每次100字节,而recvfrom时buff为1024,会不会同时把这二个包接收到缓冲,或者会不会接收第一个包和第二个包的一部份
另外会不会由于网络原因UDP会对一个包进行分块接收
[/Quote]

不会.每次只收一个块,无论你给你缓冲有多大.
controstr 2009-07-31
  • 打赏
  • 举报
回复
会不会有像TCP一样,如果接收缓冲足够大,会不会每次接收二个包,比如sendto二次,每次100字节,而recvfrom时buff为1024,会不会同时把这二个包接收到缓冲,或者会不会接收第一个包和第二个包的一部份
另外会不会由于网络原因UDP会对一个包进行分块接收
w29468 2009-07-31
  • 打赏
  • 举报
回复
接收缓冲区小于消息块长度会丢掉当前待接收那个消息包
我辣椒哥 2009-07-31
  • 打赏
  • 举报
回复
recvfrom>=sendto 比较好
KWHOK 2009-07-31
  • 打赏
  • 举报
回复
返回的错误代码都给出了,查下不就知道什么错误了:

WSAEMSGSIZE-10040
Message too long.
A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram was smaller than the datagram itself.

翻译就不用了吧
bylea 2009-07-30
  • 打赏
  • 举报
回复
UDP,是已经消息块的形式发送的,是以为单位进行接收的,当你的::recvfrom 给的可用缓冲区小于当前消息块时,UDP认为这个消息块无法完成传送,就会产生错误.

所以说::recvfrom 给的缓头冲区最好大些,通常说64KB就完全可以了(不关心内存的消耗的情况).

dl551djs 2009-07-30
  • 打赏
  • 举报
回复
sendto 明明发来的是100字节啊,不是按有多少数据来计算。
收的地方当然要字节相同啊,甚至大点也没关系,但不能比发的小。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧