孙鑫vc++ 异步套接字 编程如下代码:(在VC++6.0中编译,执行没问题,发送接收都正常)
接收时,消息处理:void CAsyncDlg::OnSock(WPARAM wParam,LPARAM lParam)
{
switch (LOWORD(lParam))
{
case FD_READ:
WSABUF wsabuf;
wsabuf.buf=new char[200];
wsabuf.len=200; DWORD dwRead;
DWORD dwFlag=0; /////
SOCKADDR_IN addrRecv;
int len=sizeof(SOCKADDR); ///// if (SOCKET_ERROR==WSARecvFrom(m_socket,&wsabuf,1,&dwRead,&dwFlag,(SOCKADDR*)&addrRecv,&len,NULL,NULL))
{
MessageBox("接收数据失败");
return ;
} CString str,strTemp; str.Format("%s说 : %s",inet_ntoa(addrRecv.sin_addr),wsabuf.buf);
str=str+"\r\n";
GetDlgItemText(IDC_EDIT_RECV,strTemp);
str=str+strTemp;
SetDlgItemText(IDC_EDIT_RECV,str); break;
}
}
发送时:void CAsyncDlg::OnBtnSend() 
{
// TODO: Add your control notification handler code here
CString str;
GetDlgItemText(IDC_EDIT_SEND,str);
int len;
len=str.GetLength(); ///// WSABUF wsabuf;
wsabuf.buf=str.GetBuffer(len);
wsabuf.len=len+1; ///// DWORD dwIP;
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
SOCKADDR_IN addrSend;
addrSend.sin_addr.S_un.S_addr=htonl(dwIP);
addrSend.sin_family=AF_INET;
addrSend.sin_port=htons(6000); DWORD dwSend; if (SOCKET_ERROR==WSASendTo(m_socket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&addrSend,sizeof(SOCKADDR),NULL,NULL))
{
MessageBox("数据发送失败");
return;
}
SetDlgItemText(IDC_EDIT_SEND,"");
}问题:
我把它,改写到vs2008中,就有问题了。
接收:LRESULT CAsyncDlg::OnSock(WPARAM wParam, LPARAM lParam)
{
switch(LOWORD(lParam))
{
case FD_READ:
WSABUF wsabuf;
wsabuf.buf=new char[200];
wsabuf.len=200; SOCKADDR_IN addrRecv;
int len=sizeof(SOCKADDR); DWORD dwRecv;
DWORD dwFlag=0; if (SOCKET_ERROR==WSARecvFrom(m_socket,&wsabuf,1,&dwRecv,&dwFlag,(SOCKADDR*)&addrRecv,&len,NULL,NULL))
{
MessageBox(_T("WSARecvFrom"),_T("ERROR"));
return 0;
} CString str,strTemp;
str.Format(_T("%s说 : %s"),inet_ntoa(addrRecv.sin_addr),wsabuf.buf);
str=str+_T("\r\n"); GetDlgItemText(IDC_EDIT_RECV,strTemp);
strTemp=str+strTemp;
SetDlgItemText(IDC_EDIT_RECV,strTemp); break;
}// return LRESULT();
return 1;
}
发送:void CAsyncDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT_SEND,str);
// str=str+_T("\0");
int len;
len=str.GetLength(); WSABUF wsabuf;
wsabuf.buf=(CHAR *)str.GetBuffer(len);
wsabuf.len=len*2+1;  //本来是和VC++6.0中一样的"wsabuf.len=len+1;",看到"Buffer too small"后改成现在这样还是 错MessageBox(LPCTSTR(wsabuf.buf),_T(""));

DWORD dwIP;
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP); SOCKADDR_IN addrSend;
addrSend.sin_addr.S_un.S_addr=htonl(dwIP);
addrSend.sin_family=AF_INET;
addrSend.sin_port=htons(6000);MessageBox(_T("1"),_T("")); DWORD dwSend;
try
{
if (SOCKET_ERROR==WSASendTo(m_socket,&wsabuf,1,&dwSend,0,(SOCKADDR*)&addrSend,sizeof(SOCKADDR),NULL,NULL))    /////--------①
{
MessageBox(_T("WSASendTo failed"),_T("ERROR"));
return;
}
}
catch (CException* e)
{
TCHAR tc[255];
e->GetErrorMessage(tc,255);
AfxMessageBox(tc);
}
MessageBox(_T("2"),_T("")); SetDlgItemText(IDC_EDIT_SEND,_T(""));
}
环境:虚拟机 windows server 2008 、vs2008现象:
1、在vs界面直接按"启动调试(小三角)"运行,输入“127.0.0.1”,不报错,能发送接收数据,但是接收到得数据:“㈱⸷⸰⸰1멸몭몭몭몭몭说 : 111촀췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍췍﷽﷽ꮫꮫꮫꮫﻮﻮ”(发送时数据为"111") 。请问为何??
2、在程序目录,找到相应exe,直接运行,,输入“127.0.0.1”,发送信息为随手输几个字母,点击发送,报错:
“Debug Assertion Failed!Program:C:\.................\Debug\Async.exe
File:f:\dd\vctools\crt_bld\self_x86\crt\src\vswprint.c
Line:280Expression:("Buffer too small",0)For information on how your program can cause an assertion failed,see the Visual C++ documentation on asserts.(Press Retryto debug the application)”
发现应该是程序中①处引起,改了"wsabuf.len"还是这样,加了如上代码的try catch还是这样。请问为何??如上错误信息中"File:f:\dd\vctools\crt_bld\self_x86\crt\src\vswprint.c"此句是干嘛的?我虚拟机中只有C盘,这句是啥意思?小弟菜鸟,请大家指点。

解决方案 »

  1.   

    可能是字符集的问题,在项目属性里设置字符集为多字符集,不要用"UNICODE",试一下
      

  2.   

    应该是字符集的问题,vs2008默认是unicode字符,vc6默认是ANSI字符集
      

  3.   

    VS2008中默认使用Unicode字符集,字符串缓冲区长度是(len+1)*sizeof(TCHAR)。这样改:
    CString str;
    GetDlgItemText(IDC_EDIT_SEND,str);
    WSABUF wsabuf;
    wsabuf.buf=(char*)(LPCTSTR)str;
    wsabuf.len=(str.GetLength()+1)*sizeof(TCHAR);
      

  4.   

    另外,"File:f:\dd\vctools\crt_bld\self_x86\crt\src\vswprint.c"是根据你生成程序的环境来提示的,与运行环境无关。
      

  5.   

    果然 为字符集 问题1、改为 "多字符集" 之后一切问题解决2、还是"Unicode字符集",用cnzdgs的方式,接收数据,后半段是对了,前半段 还不对(例如: “㈱⸷⸰⸰1멸몭몭몭몭몭 说 : 111”)
    即 应该是"str.Format(_T("%s说 : %s"),inet_ntoa(addrRecv.sin_addr),wsabuf.buf);"这一句,怎么改?? 我改为 "str.Format(_T("%s 说 : %s"),(char*)(LPCTSTR)inet_ntoa(addrRecv.sin_addr),wsabuf.buf);"--->还是那样。
      

  6.   

    把最后一句的(char *)去了
    str.Format(_T("%s 说 : %s"),(LPCTSTR)inet_ntoa(addrRecv.sin_addr),(LPCTSTR)wsabuf.buf);
      

  7.   

    VS不会这么强大吧,把虚拟机外面的环境也读出来?
    F应该是你虚拟机内的盘符
      

  8.   

    TO  8楼
    不对 还是前半句不对
    虚拟机 一个C盘、软盘为A、DVD光驱为D,其他没了
      

  9.   


    就是这个东东是在pdb文件里保存的,微软编译时自动生成的。
    你调试时它找不到相应的文件后,就自动提示编译时的环境。
      

  10.   

    inet_ntoa得到的是多字节字符串,可以用CA2T转换,或者不用inet_ntoa函数,自己用_T("%d.%d.%d.%d")的格式生成字符串。
      

  11.   

    没错,用ATL的一些函数很好用
      

  12.   

    改成 这样就行, 是为什么? "str.Format(_T("%s 说 : %s"),CString(inet_ntoa(addrRecv.sin_addr)),wsabuf.buf);"
      

  13.   

    中农,就这水平?呵呵,原谅我口直吧,从VC6到VC8还是有很多变化的
    能行自然可联想到CSTRING自动帮你把Multibyte转成Unicode了还有什么疑问啊