|
|
【参加讨论】 天极it资讯短信服务 电脑小技巧 | 介绍:细处着手,巧处用功。高手和菜鸟之间的差别就是:高手什么都知道,菜鸟知道一些。电脑小技巧收集最新奇招高招,让你轻松踏上高手之路。(首月免费) | |
随着计算机网络化的深入,计算机网络编程在程序设计的过程中变得日益重要。许多文章都曾经介绍过用vc++进行socket编程的方法。但由于都是直接利用动态连接库wsock32.dll进行操作,实现比较繁琐。其实,vc++的mfc类库中提供了casyncsocket这样一个套接字类,用它来实现socket编程,是非常方便的。
客户端
创建一个dialog based项目:csockclient。设计一对话框,增加id_connect(连接)、id_send(发送)、id_exit(关闭)按钮,增加listbox控件idc_listmsg和edit控件idc_editmsg,并按下表在classwizard中为ccsockclientdlg类添加变量。
control id type member idc_editmsg cedit m_msg idc_listmsg clistbox m_msgs |
在mysock.ccp中添加以下代码:
#include "csockclient.h" #include "csockclientdlg.h" |
在mysock.h中添加以下代码:
public: bool m_bconnected; uint m_nlength; char m_szbuffer[4096]; |
在mysock.ccp中重载各函数
mysock::mysock() { m_nlength=0; memset(m_szbuffer,0,sizeof(m_szbuffer)); m_bconnected=false;} mysock::~mysock() { //关闭套接字 if(m_hsocket!=invalid_socket) close(); } void mysock::onreceive(int nerrorcode) { m_nlength=receive(m_szbuffer,sizeof(m_szbuffer),0); //下面两行代码用来获取对话框指针 ccsockclientapp* papp=(ccsockclientapp*)afxgetapp(); ccsockclientdlg* pdlg=(ccsockclientdlg*)papp- >m_pmainwnd; pdlg- >m_msgs.insertstring(0,m_szbuffer); memset(m_szbuffer,0,sizeof(m_szbuffer)); casyncsocket::onreceive(nerrorcode);} void mysock::onsend(int nerrorcode) { send(m_szbuffer,m_nlength,0); m_nlength=0; memset(m_szbuffer,0,sizeof(m_szbuffer)); //继续提请一个“读”的网络事件,接收server消息 asyncselect(fd_read); casyncsocket::onsend(nerrorcode);} void mysock::onconnect(int nerrorcode) { if (nerrorcode==0) { m_bconnected=true; ccsockclientapp* papp=(ccsockclientapp*)afxgetapp(); ccsockclientdlg* pdlg=(ccsockclientdlg*)papp- >m_pmainwnd; memcpy(m_szbuffer,"connected to ",13); strncat(m_szbuffer,pdlg- >m_szserveradr, sizeof(pdlg- >m_szserveradr)); pdlg- >m_msgs.insertstring(0,m_szbuffer); asyncselect(fd_read);}//提请一个“读”的网络事件,准备接收 casyncsocket::onconnect(nerrorcode); }
|
建一对话框idd_addr,用来输入ip地址和port;增加两个edit控件:idc_addr、idc_port按下表在classwizard中为caddrdlg类添加变量。
control id type member idc_addr cstring m_addr idc_port int m_port |
在csockclientdlg.ccp中添加代码:
#include "addrdlg.h" protected: int trycount; mysock m_clientsocket; uint m_szport; public: char m_szserveradr[256]; |
双击idd_csockclient_dialog对话框中的“连接”按钮,添加以下代码:
m_clientsocket.shutdown(2); m_clientsocket.m_hsocket=invalid_socket; m_clientsocket.m_bconnected=false; caddrdlg m_dlg; m_dlg.m_port=1088;//默认端口1088 if (m_dlg.domodal()==idok && !m_dlg.m_addr.isempty()) { memcpy(m_szserveradr,m_dlg.m_addr,sizeof(m_szserveradr)); m_szport=m_dlg.m_port; settimer(1,1000,null);//建立计时器,每1秒尝试连接一次 trycount=0;} |
添加windows消息wm_timer响应函数ontimer
void ccsockclientdlg::ontimer(uint nidevent) { if (m_clientsocket.m_hsocket==invalid_socket) { bool bflag=m_clientsocket.create(0,sock_stream,fd_connect); if(!bflag) { afxmessagebox("socket error!"); m_clientsocket.close(); postquitmessage(0); return;}} m_clientsocket.connect(m_szserveradr,m_szport); trycount++; if (trycount >=10 || m_clientsocket.m_bconnected) { killtimer(1); if (trycount >=10) afxmessagebox("connect failed!"); return;} cdialog::ontimer(nidevent);} |
双击idd_csockclient_dialog对话框中的“发送”按钮,添加以下代码:
void ccsockclientdlg::onsend() {if (m_clientsocket.m_bconnected) { m_clientsocket.m_nlength=m_msg.getwindowtext (m_clientsocket.m_szbuffer, sizeof(m_clientsocket.m_szbuffer)); m_clientsocket.asyncselect(fd_write); m_msg.setwindowtext("");}} 双击idd_csockclient_dialog对话框中的“关闭”按钮,添加以下代码: void ccsockclientdlg::onexit() { m_clientsocket.shutdown(2); //关闭socket enddialog(0);} |
运行此项目,连接时输入主机名或ip均可,casyncsocket类会自动处理。
服务端
server端的编程与client端的类似,下面主要介绍他的listen及accept函数。建立一个cnewsocket类,重载casyncsocket类的onreceive、onsend函数,如何进行信息的显示和发送可以参考client程序。本例中采用将收到信息原封不动发回的方法来实现echo功能,代码如下:
cnewsocket::onreceive(int nerrorcode) { m_nlength=receive(m_szbuffer,sizeof(m_szbuffer),0); asyncselect(fd_write);}// 直接转发消息 cnewsocket::onsend(int nerrorcode) { send(m_szbuffer,m_nlength,0);} |
建立一个cmyserversocket类,重载casyncsocket类的onaccept函数代码如下:
在myserversocket.h中声明变量
public:: cnewsocket* m_psocket; void cmyserversocket::onaccept(int nerrorcode) { cnewsocket* psocket = new cnewsocket(); if (accept(*psocket)) { psocket- >asyncselect(fd_read); m_psocket=psocket;}else delete psocket;} |
为对话框添加一个“侦听”按钮,添加如下代码:
在csockserverdlg.ccp中声明变量
public: cmyserversocket m_srvrsocket; void ccsockserverdlg::onlisten() { if (m_srvrsocket.m_hsocket==invalid_socket) { bool bflag=m_srvrsocket.create (userport,sock_stream,fd_accept); if (!bflag) { afxmessagebox(“socket error!”); m_srvrsocket.close(); postquitmessage(0); return;}} if (!m_srvrsocket。listen(1)) { int nerrorcode = m_srvrsocket.getlasterror(); if (nerror!=wsaewouldblock) { afxmessagebox(“socket error!”); m_srvrsocket.close(); postquitmessage(0); return;}}} |
casyncsocket类为我们使用socket提供了极大方便。建立socket的wsastartup过程和bind过程被简化成为create过程,ip地址类型转换、主机名和ip地址转换的过程中许多复杂的变量类型都被简化成字符串和整数操作,特别是casyncsocket类的异步特点,完全可以替代繁琐的线程操作。mfc提供了大量的类库,我们若能灵活的使用他们,便会大大提高编程的效率。
编辑:黑鹰 [发送给好友] [打印本页] [关闭窗口] [返回顶部]
上一篇:用vc++6.0实现snmp协议的方法
下一篇:vc下使用icmp实现路由跟踪
转载请注明来源:www.iyit.net
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
|
|
|