【CSocket小问题】难道UDP套接字的发送长度有限制?——【救命】

eion 2002-01-09 05:24:23
在我的程序中有下面的代码

// len = 210 前面获得的结果
if(1)
{
len = 100;
}

len = m_socket.SendTo(buffer,len,hostport,hostaddr);

则程序能够正常工作,目的机器能正确收到数据,可是………………

如果我将if(1)改为if(0),则SendTo函数发送结果len=210,但我的目的机器并未收到任何数据,I don't know why.
who can tell me why?
...全文
1045 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
vcbear 2002-01-11
  • 打赏
  • 举报
回复
UINT len;
int len = m_socket.ReceriveFrom(buff,len,hostAddr,hostPort);

len要初试话,要不然谁知道你请求读多少字节。len=sizeof(buff);
UINT len =sizeof(buff);
int len = m_socket.ReceriveFrom(buff,len,hostAddr,hostPort);


if( 0== pDoc->m_ca.m_socket.SetSockOpt(SO_RCVBUF,&buffersize,sizeof(optlen)) )
optlen是什么玩意?

eion 2002-01-11
  • 打赏
  • 举报
回复
谢谢各位,我自己搞错了——接收缓冲搞错了
eion 2002-01-11
  • 打赏
  • 举报
回复
我用
int buffersize=2048;
if( 0== pDoc->m_ca.m_socket.SetSockOpt(SO_RCVBUF,&buffersize,sizeof(optlen)) )
{
………………
}
也不管用
eion 2002-01-11
  • 打赏
  • 举报
回复
接收端只有:
CString hostAddr;
UINT hostPort;
char buffer[2048];
UINT len;
int len = m_socket.ReceriveFrom(buff,len,hostAddr,hostPort);
if( len==-1)
{
CString error;
error.Format(“%d",m_socket.GetLastError());
MessageBox(error);
return;
}
………………
vcbear 2002-01-11
  • 打赏
  • 举报
回复
setsockopt
(
hSock,
SOL_SOCKET ,
SO_RCVBUF
....
)
qiyao 2002-01-11
  • 打赏
  • 举报
回复
有那位高手,可以搞定这个!!!
http://www.csdn.net/Expert/topic/470/470143.shtm
vcbear 2002-01-11
  • 打赏
  • 举报
回复
为什么不把接受端的代码贴出来呢。

SetSockOpt封装的是winsockapi的setsockopt,建议参考一下msdn和《windows网络编程技术》关于这个api的叙述
eion 2002-01-11
  • 打赏
  • 举报
回复
还有就是如何设定CSocket的接收缓冲的大小?

to vcbear(一只平凡无知@贫穷无钱¥的熊) 
该如何解决,有解决之道吗?
eion 2002-01-11
  • 打赏
  • 举报
回复
确实也是接收端的问题,为什么接收不能超过210各字节的UDP净荷?



CSocket的SetSockOpt和GetSockOpt什么情况下可以成功调用?
vcbear 2002-01-11
  • 打赏
  • 举报
回复
10042:
在 getsockopt 或 setsockopt 调用中指定的一个未知的、无效的或不受支持的选项或层次。
eion 2002-01-11
  • 打赏
  • 举报
回复
Super 急
eion 2002-01-11
  • 打赏
  • 举报
回复
help ME!
eion 2002-01-11
  • 打赏
  • 举报
回复
我用了SetSockOpt,好像也没用,结果为
10042:
我得MessageBox()结果为Error Unknown!
下面是我的VC源代码

int buffersize=2000;
CString str="192.168.1.38";
UINT port = 9000;
int opt,optlen=sizeof(opt);
if( 0== pDoc->m_ca.m_socket.SetSockOpt(pDoc->m_ca.m_socket.GetSockName(str,port),
&buffersize,optlen,IPPROTO_TCP) )
{
int result = GetLastError();
int errCode[]={WSANOTINITIALISED,WSAENETDOWN,WSAEFAULT,WSAEINPROGRESS,WSAEINVAL,WSAENETRESET,WSAENOTCONN,WSAENOTSOCK};
char *err[]={"WSANOTINITIALISED","WSAENETDOWN","WSAEFAULT","WSAEINPROGRESS","WSAEINVAL","WSAENETRESET","WSAENOTCONN","WSAENOTSOCK"};
int codenum = sizeof(errCode)/sizeof(errCode[0]);
CString str;
for(int i=0;i<codenum;i++) if( result==errCode[i] )
{
str = err[i];
break;
}
if( i==codenum ) str = "Error Unknown!";
MessageBox(str,"SetSocketOpt");
}


qiyao 2002-01-11
  • 打赏
  • 举报
回复
有那位高手,可以搞定这个!!!
http://www.csdn.net/Expert/topic/470/470143.shtm
sam1111 2002-01-11
  • 打赏
  • 举报
回复
用WinSock API创建的socket的发送和接收缓冲区的大小默认是0x2000字节,可以用setsockopt设置,不过最大好像只能设到0xff00字节。
CSocket也差不多吧!
eion 2002-01-11
  • 打赏
  • 举报
回复
好像好难哦——还是没搞定,也不知道SetSocktOpt函数用对了没有,方正没任何作用int buffersize=8000;
CString str="192.168.1.38";
UINT port = 9000;
int opt,optlen=sizeof(opt);
ca.m_socket.SetSockOpt(pDoc->m_ca.m_socket.GetSockName(str,port),&buffersize,optlen,IPPROTO_TCP);
pDoc->m_ca.m_socket.GetSockOpt(pDoc->m_ca.m_socket.GetSockName(str,port),&buffersize,&optlen,IPPROTO_TCP);

111222 2002-01-11
  • 打赏
  • 举报
回复
主  题: <¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦\- winsock2问题 -/¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦>
作  者:cathy0505
所属论坛:Visual C++
问题点数:300
回复次数:36
人气指数:838
发表时间:2001-6-27 8:36:14

//无关内容略

if(sendto(s, buffer, sizeof(buffer), 0, (SOCKADDR *)&remote, sizeof(remote)) == SOCKET_ERROR)


printf("failed %d",WSAGetLastError());


结果输出 failed 10040
请问,这里sendto错误的10040是什么?
怎么引起的?怎么处理??




回复贴子:
 SuperProgMan(编程者) 回复于2001-6-27 8:40:16 得30分
一个在数据报套接字上发送的消息大于内部消息缓冲器或其它一些网络限制,或该用户用于接收数据报的缓冲器比数据报小。

buffer是不是太大了?
 runbuff(玩火人) 回复于2001-6-27 8:40:41 得30分

好几天不见了,你好啊。

你用的是UDP吗?

 XiangDong(木头) 回复于2001-6-27 8:41:18 得30分
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 into was smaller than the datagram itself.
From MSDN, Win32 Error Codes
 seesi(不是我想骗你,是我不知道怎么才能不骗!) 回复于2001-6-27 8:43:50 得30分
发送数据过大?
 seedundersnow() 回复于2001-6-27 8:44:28 得30分

或许,可以考虑用 FormatMessage() 试试?
用法我不太清楚,自己看msdn吧


 cathy0505() 回复于2001-6-27 8:56:43 得0分
sendto的buffer是65535那么大(string的极限)

原来buffer过大引起10040错误,那么buffer应该是多大呢?

为什么send函数同样发送这个buffer没有出现此错误呢?

sendto的buffer最大是多少?
 Kevin_qing() 回复于2001-6-27 9:03:43 得30分
sendto在局域网里面16K-32K左右差不多;
如果是拨号的话,1K-2K
 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 9:08:40 得30分
You can use getsockopt to retrieve the maximum packet size of socket with option SO_MAX_MSG_SIZE.

getsockopt (s, SOL_SOCKET, SO_MAX_MSG_SIZE, ...);

 cathy0505() 回复于2001-6-27 9:11:22 得0分
to Kevin_qing(Kevin):
这里的buffer跟接收端没有多大关系吧,
你指的是本机的buffer么?我用的是100Mb出口的服务器,发送64K应该没多大问题吧。

 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 9:22:38 得30分
通常send函数主要应用于TCP协议的数据传输,TCP本身有自己的缓冲区,send函数结束之后并不表明数据已经传到了目标机器,只是从应用程序拷贝到TCP协议栈的缓冲区罢了。

sendto函数有所不同,它主要应用于UDP协议的数据传输,而UDP协议本身是没有缓冲区的。如果传送的数据长度超过maximum packet size, 它就会出现上述的错误。

通常一个TCP socket的MPS(maximum packet size) 大于 UDP socket的 MPS。
 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 9:23:48 得30分
你可以用创建一个TCP socket和一个UDP socket 试试看。
 cathy0505() 回复于2001-6-27 9:25:22 得0分
TO xxxbird(*说你行,你就行,不行也行*) 
请告诉我getsockopt (s, SOL_SOCKET, SO_MAX_MSG_SIZE, ...);最后两个参数怎么写。我看见第4个参数型为char FAR* ,那么char*怎么指定msg的size呢?
 Sunny_lin(大和尚) 回复于2001-6-27 9:29:19 得0分
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 into was smaller than the datagram itself.

 Kevin_qing() 回复于2001-6-27 9:30:52 得30分
我指的是每次send的size,超过这个size丟包会很严重的
 Kevin_qing() 回复于2001-6-27 9:32:40 得0分

int size;
getsockopt (s, SOL_SOCKET, SO_MAX_MSG_SIZE, (LPSTR)&size,sizeof(int));

 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 9:46:31 得0分
int size, len;
len = sizeof(int);

getsockopt (s, SOL_SOCKET, SO_MAX_MSG_SIZE, (LPSTR)&size, &len);

 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 9:47:45 得0分
实际上getsockopt函数对TCP socket不起作用,我上面弄错了。
 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 9:50:51 得0分
>>sendto的buffer是65535那么大(string的极限)

>>原来buffer过大引起10040错误,那么buffer应该是多大呢?

在我的系统中是65527, 我想加上UDP协议头之后应该正好是65535了。


 cathy0505() 回复于2001-6-27 9:50:55 得0分
int msg_size = 65535;
getsockopt(s, SOL_SOCKET, SO_MAX_MSG_SIZE, (LPSTR)&msg_size,sizeof(int));

oicqsend.c
C:\WINDOWS\Desktop\oicqsend\oicqsend.c(335) : warning C4047: 'function' : 'int *' differs in levels of indirection from 'unsigned int '
C:\WINDOWS\Desktop\oicqsend\oicqsend.c(335) : warning C4024: 'getsockopt' : different types for formal and actual parameter 5
Linking...


这两个警告又是怎么回事呢?对不起,我初学,什么都不大懂


 plato(天天) 回复于2001-6-27 9:53:20 得0分
UDP包的最大限制是65535个字节
 cathy0505() 回复于2001-6-27 9:53:39 得0分
65527?那int msg_size = 65527;
但是两个警告怎么处理呢?还不知道这样会不会出现10040错误呢
 Kevin_qing() 回复于2001-6-27 9:58:48 得0分
不好意思,刚才写错了:

int msg_size ;
int size=sizeof(msg_size);
getsockopt(s, SOL_SOCKET, SO_MAX_MSG_SIZE, (LPSTR)&msg_size,&size);

如果成功的话,msg_size 就是你要的东西



 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 10:09:00 得0分
你需要用getsockopt返回的大小设置你的缓冲区,而不要用硬编码,因为你的系统可能和我的不一样,而且最终用户的系统也有可能和你的不一样。

警告的处理可将int msg_size 改为 unsigned int 就可以了。最后一个参数不能用 sizeof.

 cathy0505() 回复于2001-6-27 10:37:37 得0分
按照Kevin_qing(Kevin) 的方法就没有警告了。
但运行的结果是,同样出现10040错误

我要写的程序是轰炸OICQ之用
修改了自己的IP
相关请看
http://member.netease.com/~wxb/works/oicqsend.htm


难道发送65535字节大小的数据一定要用tcp连接?难道轰炸OICQ要用tcp连接?

 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-27 10:50:50 得0分
哇,动机不纯!

你不好一次少发一点么?



 field() 回复于2001-6-27 11:03:46 得0分


ooh, i love you very much.



 runbuff(玩火人) 回复于2001-6-27 13:20:22 得0分

To cathy0505()
你还是原来的cathy0505()?我怀疑你是盗用别人的ID。
cathy0505()是一位好MM,怎么说出轰炸OICQ之类令人恐怖的话?!


 kylix2001(小小®)(我是真的) 回复于2001-6-27 13:36:33 得0分
是呀是呀。。。
:)
 flywhc(午夜蓝调) 回复于2001-6-27 14:29:27 得0分
我想你是把上面那段放一个循环里了?
考虑用none-blocking的socket, 使用WSAAsyncSelect,在FD_READ的处理中发数据,而发的UDP数据包一般不超过512字节,比较保险。
 gPolaris(星星之火) 回复于2001-6-27 16:27:21 得0分
flywhc(午夜蓝调)说的好
 lgs(心不在馬) 回复于2001-6-27 16:31:41 得0分
sizeof(buffer)错误,
应该用strlen(buffer)。
 czylj(夭夭) 回复于2001-6-27 20:14:46 得0分
┏━┯━┓
┃夭 夭┃
┠ 印 ┨
┃夭 夭┃
┗━┷━┛
 wangyi03(小楼一夜听春雨) 回复于2001-6-27 20:20:01 得0分
啊,你还会搞这个啊,:))
 greentea(绿茶) 回复于2001-6-28 9:03:52 得0分
具体的错误消息为:
一个在数据报套接字上发送的消息大于内部消息缓冲器或其它一些网络限制,或该用户用于接收数据报的缓冲器比数据报小。
你可以使用vc++6.0-〉tools ->error lookup->键入10040,点击"lookup"就可以看到,
从错误分析来看,socket内部发送时,维护了一个缓冲,你的缓冲容量显然比socket内部的缓冲要大,建议分包发送,为了提高效率,udp包的大小小于等于256bytes
 xxxbird(*说你行,你就行,不行也行*) 回复于2001-6-28 9:21:41 得0分
理论上一个IP包最大可能有65535字。而UDP是基于IP的,去掉IP头(至少20字节),UDP头(8字节),这样理论上一个UDP包最多就只能发送65507个字节。但在TCP/IP协议栈实际的实现中,很少有达到这个数目的。而且考虑到网络的MTU大小(一般的以太网为1500字节),IP会将大的数据包分段。这样如果数据包过大,将会被分成许多段,这许多段只要有一个在传输过程中出了问题,整个UDP包就会丢失。因此,建议在使用UDP协议时,每次发送的数据量不宜太大,通常以不超过本地的MTU为宜。
 xianserver(我要学习,你有什么好东西我都要!) 回复于2001-6-28 20:53:38 得0分
10040:数据报太大,不适于缓冲区的要求,因而被截断

这样简单的方法很简单的就会被防火墙拦截的!
eion 2002-01-11
  • 打赏
  • 举报
回复
那CSocket的默认Buffer是多少?如果太少,该如何设定他的大小呢?
wwwsq 2002-01-11
  • 打赏
  • 举报
回复
SendTo应该是成功的,那多半是接收有问题。比如接收的Buffer你可能只开了100或者200字节。
shesh 2002-01-11
  • 打赏
  • 举报
回复
udp的长度确实是在8K左右.
强制也不行.
加载更多回复(10)

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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