UDP发送位图,为什么只有最后的一百个字节正确?

wmnmtm 2011-04-06 11:42:45
VC6,UDP传送

我做了一个24色的bmp位图(很小,上面写了12两个字符),占用1134字节,我在本机测试:

用CFile把位图读到char[2048]里(为了保证读入正确,读完后把char[2048]缓冲换个文件名重写到硬盘,图片写入正确)。

用SOCKET的UDP方式把缓冲区发送到接收方(实际都是127.0.0.1的8000端口),接收后把接收缓冲区写入文件,结果图片除了大小对外,不能预览,用二进制查看器与原文件比较,发现只是最后末尾的100个字节对,前面全是00000000(一千多个0),

以为是网络问题,所以换成一1134个长的字符串发送,结果用二进制查看器查看(以字符方式)收到的文件,发现完全正确。


以下是相关的几段代码:


CFile file;
if(!file.Open(m_strPathName, CFile::modeRead | CFile::typeBinary))
{
AfxMessageBox("打开文件失败");
return ;
}


//假设一次读完,当然大文件得循环读,此处只为测试
ilen = file.Read(bufx, 1134);//ilen = file.Read((void*)bufx, 1134);


void CTest2Dlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
WORD wVersionRequested;
WSADATA wsadata;

wVersionRequested = MAKEWORD(2,2);

int nErrCode;
nErrCode = WSAStartup(MAKEWORD(2,2),&wsadata);

if (0 != nErrCode)
{
//没有找到可用的套接字
AfxMessageBox("没有找到可用的DLL");
}

SOCKET socket1;
socket1 = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN sockaddr_in1;
ZeroMemory(bufx,1024);
sockaddr_in1.sin_addr.s_addr=inet_addr("127.0.0.1");
sockaddr_in1.sin_family=AF_INET;
sockaddr_in1.sin_port=htons((short)8000);

long iLength;
iLength = sendto(socket1,bufx,1134,0,(SOCKADDR*)&sockaddr_in1,sizeof(sockaddr_in1));
}


下面是接收的代码:


void CServerDlg::OnBtnRecv()
{
// TODO: Add your control notification handler code here
SOCKADDR_IN sockaddr_in1;
SOCKET socket1;
// char buf[2048];
int nClientLen;

WORD wVersionRequested;
WSADATA wsadata;

wVersionRequested = MAKEWORD(2,2);

int nErrCode;
nErrCode = WSAStartup(MAKEWORD(2,2),&wsadata);

if (0 != nErrCode)
{
//没有找到可用的套接字
//MessageBox(NULL,"没有找到可用的DLL","初始化失败",MB_OK);
}


sockaddr_in1.sin_addr.s_addr=htonl(INADDR_ANY);
sockaddr_in1.sin_family=AF_INET;
sockaddr_in1.sin_port=htons((short)8000);

nClientLen = sizeof(sockaddr_in1);

socket1 = socket(AF_INET,SOCK_DGRAM,0);

bind(socket1,(SOCKADDR*)&sockaddr_in1,nClientLen);
memset(buf,0,sizeof(buf));

iLengthRecv = recvfrom(socket1,buf,sizeof(buf),0,(SOCKADDR*)&sockaddr_in1,&nClientLen);

CString m_strFilePath;
m_strFilePath="c:\\123.jpg";
UINT rcv;
//接受并保存文件。
CFile file(m_strFilePath, CFile::modeCreate | CFile::modeWrite);

file.Write(buf, iLengthRecv);//把接收缓冲区原封不动的存为文件

file.Close();

}

结果就如开始说的那样,只有最后一百个了节对,前面全是0000;

我专门在发送时指定了一个一千多字节的"1234567890ABVDEF12343....",结果收到正确。

请高人指点一下为什么会这样?(不用说拆包发送,只需要一次发送很小的位图)

...全文
146 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
wmnmtm 2011-04-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 mengfeihong 的回复:]
这个应该是代码问题的。
看你的表述,应该是一次性把所有位图数据读到一个缓冲,然后一次性把缓冲发完。那应该很简单啊,你就下断点,先看看发送前的数据读对了没有。
[/Quote]

四楼的兄弟,我读到缓冲区后,又把缓冲区写了一遍,确认是读对了的。
wmnmtm 2011-04-06
  • 打赏
  • 举报
回复
还有一个现象是,发送txt文件也不对,和发送位图文件一样的性质,只是直接发送字符串的话,接收是对的。
wmnmtm 2011-04-06
  • 打赏
  • 举报
回复
楼上两位,我用的是一个极小的位图,所以不用考虑覆盖的问题

也不用考虑丢包的问题,只是一个1134字节的小位图,只为测试一个小问题,不是实用。
蒙飞鸿 2011-04-06
  • 打赏
  • 举报
回复
这个应该是代码问题的。
看你的表述,应该是一次性把所有位图数据读到一个缓冲,然后一次性把缓冲发完。那应该很简单啊,你就下断点,先看看发送前的数据读对了没有。
King_hhuang 2011-04-06
  • 打赏
  • 举报
回复
你能确保你每次OnRecive都能把数据接收完吗
另外你写文件,应该是追加,不要覆盖
CFile file(m_strFilePath, CFile::modeCreate | CFile::modeWrite);
file.SeekToEnd();
file.Write(buf, iLengthRecv);//把接收缓冲区原封不动的存为文件
傻X 2011-04-06
  • 打赏
  • 举报
回复
要循环读取的,你就写了一次,当然之前的东西都被你替换掉了
wmnmtm 2011-04-06
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 mengfeihong 的回复:]
ZeroMemory(bufx,1024);
sockaddr_in1.sin_addr.s_addr=inet_addr("127.0.0.1");
sockaddr_in1.sin_family=AF_INET;
sockaddr_in1.sin_port=htons((short)8000);

long iLength;
iLength = sendt……
[/Quote]

是啊,汗,真的是我清零了,谢谢楼上
蒙飞鸿 2011-04-06
  • 打赏
  • 举报
回复
ZeroMemory(bufx,1024);
sockaddr_in1.sin_addr.s_addr=inet_addr("127.0.0.1");
sockaddr_in1.sin_family=AF_INET;
sockaddr_in1.sin_port=htons((short)8000);

long iLength;
iLength = sendto(socket1,bufx,1134,0,(SOCKADDR*)&sockaddr_in1,sizeof(sockaddr_in1));



这个明显有问题嘛,自己刚把前面1024清零了,就发送了,那那边前1024肯定是0了。
wmnmtm 2011-04-06
  • 打赏
  • 举报
回复
我的QQ:1023266328,麻烦加我发代码给你试试,谢谢啊
Eleven 2011-04-06
  • 打赏
  • 举报
回复
ZeroMemory(bufx,1024);

iLength = sendto(socket1,bufx,1134,0,(SOCKADDR*)&sockaddr_in1,sizeof(sockaddr_in1));

先Debug下调试一下,看看是发送端的问题还是接收端处理的问题~


wmnmtm 2011-04-06
  • 打赏
  • 举报
回复
难道你们回帖就不看吗,我说的是发送一个很小的位图,仅此而已,不要引申到太复杂了
wpllg 2011-04-06
  • 打赏
  • 举报
回复
可以采用可靠传输协议,比如UDT,UDX协议,还有VTCP协议,他们都是基于UDP基出之上的.

18,356

社区成员

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

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