我在SDI的View中加载了一个Dialog,然后在Dialog中注册网络事件,进行基于TCP的socket通信,但是现在发现这些事件没有响应,请问是怎么回事? 基于AsyncSelect模型的网络应用,直接用MFC封装好的CSocked就好了 简单健壮 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 to allenhiman:谢谢了 我先看下! WSAAsyncSelect是什么时候执行的?ConnSocket是什么样的SOCKET? to cnzdgs:1)SOCKET ConnSocket;2)WSAAsyncSelect 是在单击m_TPTDlg实例上的按钮之后通过线程调用执行的void CTPTMPTComCfig::OnBtnStart() { CString str="服务器:"+GetIPAddress()+"端口号:2000正在进行监听"; m_ctlMsgList.InsertItem(i++,str); //ServerSocket在初始化对话框时赋值,用于监听,默认连接个数:5 int isListenOk=listen(ServerSocket,5);//启动监听,P77 if (0!=isListenOk) { MessageBox("侦听失败!"); return ; } //pServerThread:启动工作线程;等待客户请求到来;调用1.1 pServerThread=AfxBeginThread(Server,0);}UINT Server(LPVOID p){ int len=sizeof(SOCKADDR); //1. 获得当前运行对话框句柄 CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd(); CFrameWnd* SDI=(CFrameWnd*)AfxGetApp()->GetMainWnd(); CPictureView* pView=(CPictureView*)SDI->GetActiveView(); //SOCKET tepSock=dlg->ServerSocket; SOCKET tepSock=ServerSocket; //sockCon和ConnSocket成员为具体工作(传输数据等)的套接字TCP连接的套接字 //单独定义sockCon是为了方便错误判断和处理 SOCKET sockCon=accept( tepSock,(SOCKADDR*)&(dlg->localaddr),&len); //dlg->ConnSocket=sockCon; ConnSocket=sockCon; if(sockCon==INVALID_SOCKET) { AfxMessageBox("连接失败!"); } //连接成功;注册网络事件,将端口设置为非阻塞模式 //NETWORK_EVENT为待接收的消息,在1.2中进行处理 //FD_READ|FD_WRITE|FD_CLOSE:准备好读、写和关闭网络连接 int socketSel=WSAAsyncSelect(ConnSocket,pView->m_hWnd, NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE); if(SOCKET_ERROR==socketSel) { AfxMessageBox("注册网络事件失败!"); return 0; } return 0;}谢谢! 消息是在CPictureView类中响应的吗?你的程序搞的太复杂了,既然要用WSAAsyncSelect,就不要另创建线程了,把listen的socket也用WSAAsyncSelect注册消息来处理。另外,WSAAsyncSelect也许不能这样跨线程使用,没这样试过。 to cnzdgs: 1)消息也是在m_CTPTDialog 中响应的,所有的消息注册消息响应都是在在CTPTDialog 中进行处理的;我跟踪了下注册似乎成功了,但就是没有响应,难道是没有注册时的窗口句柄有问题?到底是用哪个句柄呢? WSAAsyncSelect中指定的窗口句柄是pView->m_hWnd,所以要在CPictureView类中响应;如果要在对话框类中响应,要指定对话框的窗口句柄。 //定义用户消息#define NETWORK_EVENT WM_USER+166//定义网络事件#define WM_PAUSE WM_USER+177 //定义暂停消息#define WM_STOP WM_USER+178// 定义暂停消息#define WM_CONTINUE WM_USER+179//定义继续消息#define WM_SYN WM_USER+180 //定义同步消息#define WM_MONITOR WM_USER+181 //定义监控消息//声明消息处理函数,响应用户消息afx_msg void OnNetEvent(WPARAM wParam,LPARAM lParam);afx_msg void OnPause(WPARAM wParam,LPARAM lParam);afx_msg void OnStop(WPARAM wParam,LPARAM lParam);afx_msg void OnContinue(WPARAM wParam,LPARAM lParam);afx_msg void OnSyn(WPARAM wParam,LPARAM lParam);afx_msg void OnMonitor(WPARAM wParam,LPARAM lParam);void CTPTMPTComCfig::OnNetEvent(WPARAM wParam,LPARAM lParam){ ... case FD_READ: { AfxBeginThread(RecvProc,0);//启动接收进程,调用1.3 break; } ...}UINT RecvProc(LPVOID lpvoid){ char buf[1029];//定义接收缓存 CString str;//中间变量 int k; CTPTMPTComCfig* pdlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd(); int n=recv(CurSock,buf,1028,0);//CurSock:已经建立TCP通信的套接字 if (SOCKET_ERROR==n) { AfxMessageBox("连接未正常关闭!"); } buf[n]='\0'; //1. 判断是否为测试例数据 if((strchr(buf,'-')!=NULL)) { str=buf; pdlg->m_testcase[pdlg->count]=buf;//将测试例保存下来 pdlg->count++;//移动测试例计数 pdlg->m_ctlMsgList.InsertItem(pdlg->i++,buf);//显示所保存的测试例的名称 k=pdlg->FindNumber();//查找IP地址在列表中对应的序号(从零起),调用1.4 str="TPT"+TPTInfo[k].num+":"+"测试例"+str+"已经收到!"; //if( send(pdlg->CurSock,str,str.GetLength(),0)==SOCKET_ERROR)//通知客户端 if( send(CurSock,str,str.GetLength(),0)==SOCKET_ERROR)//通知客户端 { AfxMessageBox("发送数据错误!"); } } //2. 判断是否为控制命令 else if( strcmp(buf,"START")==0)//1. 响应客户端'开始测试'消息,调用'开始测试'线程 { m_pStartThread=AfxBeginThread(StartTest,0);//调用1.6,启动“开始测试”工作线程 } else if(strcmp(buf,"PAUSE")==0)//2. 暂停,响应客户端'暂停测试'消息,通过消息机制 { ::PostMessage(pdlg->m_hWnd,WM_PAUSE,0,0);//调用1.7 } else if(strcmp(buf,"STOP")==0)//3. 停止,响应客户端'停止测试'消息,通过消息机制 { ::PostMessage(pdlg->m_hWnd,WM_STOP,0,0);//调用1.8 } else if(strcmp(buf,"CONTINUE")==0)//4. 继续,响应客户端'继续执行测试'消息 { ::PostMessage(pdlg->m_hWnd,WM_CONTINUE,0,0);//调用1.9 } else if(strcmp(buf,"SYN")==0)//5. 同步,响应客户端'同步测试'命令,并在本地进行处理(消息响应) { ::PostMessage(pdlg->m_hWnd,WM_SYN,0,0);//调用1.10 } else if(strcmp(buf,"MONITOR")==0)//6. 监控,响应客户端'监控测试'命令,并在本地进行处理(消息响应) { ::PostMessage(pdlg->m_hWnd,WM_MONITOR,0,0);//调用1.11 } else pdlg->m_ctlMsgList.InsertItem(pdlg->i++,buf);//7. 其他 return 0;}说明:1)这些函数全在CTPTMPTComCfig类文件中2)CTPTMPTComCfig是由CDialog继承而来的! UINT Server(LPVOID p){ int len=sizeof(SOCKADDR); //1. 获得当前运行对话框句柄 CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd(); SOCKET tepSock=ServerSocket; //sockCon和ConnSocket成员为具体工作(传输数据等)的套接字TCP连接的套接字 //单独定义sockCon是为了方便错误判断和处理 SOCKET sockCon=accept( tepSock,(SOCKADDR*)&(dlg->localaddr),&len); //dlg->ConnSocket=sockCon; ConnSocket=sockCon; if(sockCon==INVALID_SOCKET) { AfxMessageBox("连接失败!"); } //连接成功;注册网络事件,将端口设置为非阻塞模式 //NETWORK_EVENT为待接收的消息,在1.2中进行处理 //FD_READ|FD_WRITE|FD_CLOSE:准备好读、写和关闭网络连接 int socketSel=WSAAsyncSelect(ConnSocket,dlg->m_hWnd, NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE); if(SOCKET_ERROR==socketSel) { AfxMessageBox("注册网络事件失败!"); return 0; } return 0;}中的:......CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();......int socketSel=WSAAsyncSelect(ConnSocket,dlg->m_hWnd, NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);这两句是不是已经获得了Dialog的窗口句柄呢?谢谢!另外: 怎么给分呢? 你说的除了把“把listen的socket也用WSAAsyncSelect注册消息来处理”之外的方法:1)WSAAsyncSelect中指定的窗口句柄是pView->m_hWnd,所以要在CPictureView类中响应:......CFrameWnd* SDI=(CFrameWnd*)AfxGetApp()->GetMainWnd();CPictureView* pView=(CPictureView*)SDI->GetActiveView(); ......int socketSel=WSAAsyncSelect(ConnSocket,pView->m_hWnd, NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);2)如果要在对话框类中响应,要指定对话框的窗口句柄:......CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();......int socketSel=WSAAsyncSelect(dlg->ConnSocket,dlg->m_hWnd, NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);我似乎都尝试过,但还是没响应;另外:我尝试了“把listen的socket也用WSAAsyncSelect注册消息来处理”,这里注册了之后似乎accept()之后建立的通信套接字就不能注册了?难道两个都注册?请解释下,谢谢! 我用侦听套接字注册网络事件之后在该套接字的基础上似乎就不能accept从而产生合法的通信套接字!谢谢! 你的程序是SDI架构,AfxGetApp()->GetMainWnd()获得的是主框架类对象,不是对话框类对象,如果对话框类对象是在视图类中定义的,可以先获取视图类指针,然后再用该指针访问对话框对象。或者在创建线程的时候把对话框指针作为参数传给线程。 to cnzdgs:谢谢哈 我尝试着做下!再反馈情况! to cnzdgs: 非常感谢,我使用this指针就可以了!谢谢了!再次感谢! 怎么给定起点和终点的数据在mapobjects上用drawshape函数或其他可用函数画线 请高手帮忙看看怎么编这个程序 CImagelist 中位图怎么缩放 急救:在开发自己的gina.dll(usbkey)时遇到一件比较郁闷的事情,请各位大虾帮帮忙!! CListCtr问题请教高手 求多页显示样式的工具栏 请教一个关于文件保存的问题 快来看看 在线统计:你们公司用vc开发些什么软件啊!! 谁能告诉我这是为什么. debug & release 如何改变windows默认窗口外观(C语言API编程) VC里LINK报错
谢谢了 我先看下!
1)SOCKET ConnSocket;
2)WSAAsyncSelect 是在单击m_TPTDlg实例上的按钮之后通过线程调用执行的
void CTPTMPTComCfig::OnBtnStart()
{
CString str="服务器:"+GetIPAddress()+"端口号:2000正在进行监听";
m_ctlMsgList.InsertItem(i++,str);
//ServerSocket在初始化对话框时赋值,用于监听,默认连接个数:5
int isListenOk=listen(ServerSocket,5);//启动监听,P77
if (0!=isListenOk)
{
MessageBox("侦听失败!");
return ;
}
//pServerThread:启动工作线程;等待客户请求到来;调用1.1
pServerThread=AfxBeginThread(Server,0);
}
UINT Server(LPVOID p)
{
int len=sizeof(SOCKADDR);
//1. 获得当前运行对话框句柄
CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();
CFrameWnd* SDI=(CFrameWnd*)AfxGetApp()->GetMainWnd();
CPictureView* pView=(CPictureView*)SDI->GetActiveView(); //SOCKET tepSock=dlg->ServerSocket;
SOCKET tepSock=ServerSocket;
//sockCon和ConnSocket成员为具体工作(传输数据等)的套接字TCP连接的套接字
//单独定义sockCon是为了方便错误判断和处理
SOCKET sockCon=accept( tepSock,(SOCKADDR*)&(dlg->localaddr),&len);
//dlg->ConnSocket=sockCon;
ConnSocket=sockCon;
if(sockCon==INVALID_SOCKET)
{
AfxMessageBox("连接失败!");
}
//连接成功;注册网络事件,将端口设置为非阻塞模式
//NETWORK_EVENT为待接收的消息,在1.2中进行处理
//FD_READ|FD_WRITE|FD_CLOSE:准备好读、写和关闭网络连接
int socketSel=WSAAsyncSelect(ConnSocket,pView->m_hWnd,
NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);
if(SOCKET_ERROR==socketSel)
{
AfxMessageBox("注册网络事件失败!");
return 0;
}
return 0;
}谢谢!
你的程序搞的太复杂了,既然要用WSAAsyncSelect,就不要另创建线程了,把listen的socket也用WSAAsyncSelect注册消息来处理。另外,WSAAsyncSelect也许不能这样跨线程使用,没这样试过。
1)消息也是在m_CTPTDialog 中响应的,所有的消息注册消息响应都是在在CTPTDialog 中进行处理的;
我跟踪了下注册似乎成功了,但就是没有响应,难道是没有注册时的窗口句柄有问题?到底是用哪个句柄呢?
#define NETWORK_EVENT WM_USER+166//定义网络事件
#define WM_PAUSE WM_USER+177 //定义暂停消息
#define WM_STOP WM_USER+178// 定义暂停消息
#define WM_CONTINUE WM_USER+179//定义继续消息
#define WM_SYN WM_USER+180 //定义同步消息
#define WM_MONITOR WM_USER+181 //定义监控消息
//声明消息处理函数,响应用户消息
afx_msg void OnNetEvent(WPARAM wParam,LPARAM lParam);
afx_msg void OnPause(WPARAM wParam,LPARAM lParam);
afx_msg void OnStop(WPARAM wParam,LPARAM lParam);
afx_msg void OnContinue(WPARAM wParam,LPARAM lParam);
afx_msg void OnSyn(WPARAM wParam,LPARAM lParam);
afx_msg void OnMonitor(WPARAM wParam,LPARAM lParam);void CTPTMPTComCfig::OnNetEvent(WPARAM wParam,LPARAM lParam)
{
...
case FD_READ:
{
AfxBeginThread(RecvProc,0);//启动接收进程,调用1.3
break;
}
...
}UINT RecvProc(LPVOID lpvoid)
{
char buf[1029];//定义接收缓存
CString str;//中间变量
int k;
CTPTMPTComCfig* pdlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();
int n=recv(CurSock,buf,1028,0);//CurSock:已经建立TCP通信的套接字
if (SOCKET_ERROR==n)
{
AfxMessageBox("连接未正常关闭!");
} buf[n]='\0';
//1. 判断是否为测试例数据
if((strchr(buf,'-')!=NULL))
{
str=buf;
pdlg->m_testcase[pdlg->count]=buf;//将测试例保存下来
pdlg->count++;//移动测试例计数
pdlg->m_ctlMsgList.InsertItem(pdlg->i++,buf);//显示所保存的测试例的名称
k=pdlg->FindNumber();//查找IP地址在列表中对应的序号(从零起),调用1.4
str="TPT"+TPTInfo[k].num+":"+"测试例"+str+"已经收到!";
//if( send(pdlg->CurSock,str,str.GetLength(),0)==SOCKET_ERROR)//通知客户端
if( send(CurSock,str,str.GetLength(),0)==SOCKET_ERROR)//通知客户端
{
AfxMessageBox("发送数据错误!");
}
}
//2. 判断是否为控制命令
else if( strcmp(buf,"START")==0)//1. 响应客户端'开始测试'消息,调用'开始测试'线程
{
m_pStartThread=AfxBeginThread(StartTest,0);//调用1.6,启动“开始测试”工作线程
}
else if(strcmp(buf,"PAUSE")==0)//2. 暂停,响应客户端'暂停测试'消息,通过消息机制
{
::PostMessage(pdlg->m_hWnd,WM_PAUSE,0,0);//调用1.7
}
else if(strcmp(buf,"STOP")==0)//3. 停止,响应客户端'停止测试'消息,通过消息机制
{
::PostMessage(pdlg->m_hWnd,WM_STOP,0,0);//调用1.8
}
else if(strcmp(buf,"CONTINUE")==0)//4. 继续,响应客户端'继续执行测试'消息
{
::PostMessage(pdlg->m_hWnd,WM_CONTINUE,0,0);//调用1.9
}
else if(strcmp(buf,"SYN")==0)//5. 同步,响应客户端'同步测试'命令,并在本地进行处理(消息响应)
{
::PostMessage(pdlg->m_hWnd,WM_SYN,0,0);//调用1.10
}
else if(strcmp(buf,"MONITOR")==0)//6. 监控,响应客户端'监控测试'命令,并在本地进行处理(消息响应)
{
::PostMessage(pdlg->m_hWnd,WM_MONITOR,0,0);//调用1.11
}
else pdlg->m_ctlMsgList.InsertItem(pdlg->i++,buf);//7. 其他
return 0;
}说明:
1)这些函数全在CTPTMPTComCfig类文件中
2)CTPTMPTComCfig是由CDialog继承而来的!
{
int len=sizeof(SOCKADDR);
//1. 获得当前运行对话框句柄
CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();
SOCKET tepSock=ServerSocket;
//sockCon和ConnSocket成员为具体工作(传输数据等)的套接字TCP连接的套接字
//单独定义sockCon是为了方便错误判断和处理
SOCKET sockCon=accept( tepSock,(SOCKADDR*)&(dlg->localaddr),&len);
//dlg->ConnSocket=sockCon;
ConnSocket=sockCon;
if(sockCon==INVALID_SOCKET)
{
AfxMessageBox("连接失败!");
}
//连接成功;注册网络事件,将端口设置为非阻塞模式
//NETWORK_EVENT为待接收的消息,在1.2中进行处理
//FD_READ|FD_WRITE|FD_CLOSE:准备好读、写和关闭网络连接
int socketSel=WSAAsyncSelect(ConnSocket,dlg->m_hWnd,
NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);
if(SOCKET_ERROR==socketSel)
{
AfxMessageBox("注册网络事件失败!");
return 0;
}
return 0;
}中的:
......
CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();
......
int socketSel=WSAAsyncSelect(ConnSocket,dlg->m_hWnd,
NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);这两句是不是已经获得了Dialog的窗口句柄呢?谢谢!
另外: 怎么给分呢?
1)WSAAsyncSelect中指定的窗口句柄是pView->m_hWnd,所以要在CPictureView类中响应:
......
CFrameWnd* SDI=(CFrameWnd*)AfxGetApp()->GetMainWnd();
CPictureView* pView=(CPictureView*)SDI->GetActiveView();
......
int socketSel=WSAAsyncSelect(ConnSocket,pView->m_hWnd,
NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);
2)如果要在对话框类中响应,要指定对话框的窗口句柄:
......
CTPTMPTComCfig *dlg=(CTPTMPTComCfig*)AfxGetApp()->GetMainWnd();
......
int socketSel=WSAAsyncSelect(dlg->ConnSocket,dlg->m_hWnd,
NETWORK_EVENT,FD_READ|FD_WRITE|FD_CLOSE);
我似乎都尝试过,但还是没响应;
另外:
我尝试了“把listen的socket也用WSAAsyncSelect注册消息来处理”,这里注册了之后似乎accept()之后建立的通信套接字就不能注册了?
难道两个都注册?请解释下,谢谢!
谢谢哈 我尝试着做下!再反馈情况!
非常感谢,我使用this指针就可以了!谢谢了!再次感谢!