继续更新博客。
这段时间学的有些慢啊……
接上次的更新,一直在学孙鑫老师的VC++视频,看了多线程MFC的套接字和异步套接字的应用(至今异步套接字也不是特懂)。
但是不管怎么样,还是有长进的。
今天照着教程,把那个应用异步套接字聊天的程序,自己实例了一下。
就是应用WSAAsynselect()函数的那个。
弄完以后就出问题了,自设messagebox提示“注册网络事件失败!”,后面的功能实现不了了(后面我叙述代码,没学过孙鑫VC++的估计看着乱)。
不是编译出的错误,所以不知道哪有问题?
因为代码里messagebox跳出的条件是WSAAsynselect()==SOCKET_ERROR,所以我认为找了半天也没找到哪里错了,超级郁闷。要知道一处错误还找不到是很郁闷的(我是听没耐心的那种人),就像扔那不学了,玩游戏去。
BUT!这样是不行的,这么小的程序都找不出错误,那也太废了吧。
最后找到原因,原来是InitSock()的调用函数放错了,我放在Dlg类的构造函数了,应该放在OnInitDlg()函数里,长记性了。
再运行,试着发送信息,又定住了。“我靠,VC6就是不稳定啊”哪那么多臭毛病?
唉,再找问题,原来是一个WSArecvfrom()的函数flag参数没有初始值。让flag=0就行了。
————————————————————————分割线————————————————————————————————
//老规矩,把代码默写一遍,看看自己的记忆力如何?哈哈,默写!
//这是一个异步套接字实现的聊天程序(还是不清楚“异步套接字”的原理,前一课的多线程实现循环接收数据,我还稍微有点懂了)
//把控件资源都弄好
//在工程link里添加ws2_32.lib,在Afxstd.h添加
#include<winsock32.h>
//在CchatApp类的InitApp()函数里添加WSAStartup(),socket版本协商,从msdn靠过来例子。
//在Dlg的类里创建m_sock成员变量和InitSock()函数初始化套接字
CChatDlg::InitSock()
{
m_sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,NULL); //和上次不一样,这次是用WSASocket创建
....
....
....
//创建地址对象和绑定我已经很熟练啦!就不默写了
if(SOCKET_ERROR==WSAAsynselect(m_sock,hWnd,UM_SOCK,FD_READ)) //这个函数不是很懂
{
messagebox("注册网络时间失败!") //当时就是弹出这个,我都不知道哪错了
}
//孙鑫老师喜欢将逻辑比较的值放在前面,据说还是好习惯
}
//然后把InitSock的调用放在OnInitDlg()里而不是构造函数
//刚才的那个UM_SOCK消息和其消息响应函数Onsock定义一下,现在自定义消息响应函数也比较熟啦!
//但要注意的是,消息响应函数Onsock(WPARM,LPARAM)有两个参数,而且发生消息事件:
wParam的地位标识socket,lParam低位标识事件,lParam高位包含error code,我都不知道发生了事件,这些数据怎么传到就这两个参数里了,算了先记住吧。
//那么定义OnSock函数
CChatDlg::Onsock(WPARAM wParam,LPARAM lParam)
{
switch(LWORD(lParam)) //将lParam低位取出来switch一下
{
case FD_READ: //好像是FD_READ,忘了……
//然后要用WSArecvfrom(),但是这个函数超复杂!要一大堆参数,这个那个的
WSABUF wsabuf; //创建WSABUF结构体,这里是装数据的
wsabuf.buf=new char[200]; //还是个指针类型的,汗!
wsabuf.len=200; //结构体2成员,一个数据一个长度
DWORD dwread; //是干嘛的来着,好像是装什么长度的,反正得定义
DWORD flag=0; //由于是[in/out]参数,又得定义又得传值,要不然就出错,但我不知道干啥的。
SOCKADDR_IN addrfrom; //接收的地址
int len=sizeof(SOCKADDR); //这个好像也是[in/out]来着
WSArecvfrom(m_sock,&wsabuf,&dwread,&flag,(SOCKADDR*)addrfrom,&len,NULL,NULL);
//HOHO,这么老长的代码给默写出来了
Cstring str;
Cstring strtemp; //这两个应该放在前面,反正我先写这里了
str.format("%s 说:%s",inet_ntoa(addrfrom.Sin_addr),wsabuf.buf) //将接收到的数据格式化到str里
getDlgItemText(IDC_EDIT_RECV,strtemp);
str+="/n/r";
str+=strtemp; //把原有的保存起来
setDlgItemText(IDC_EDIT_RECV,str);
//欧了
break; //好像要有这个,break是必须有的吗?
}
}
//然后呢……
//哦,双击按钮控件创建函数,完成发送代码
CChatDlg::Onbuttonsend()
{
WSABUF wsabuf; //WSABUF结构体
DWORD dwsend;
SOCKADDR_IN addrsend; //发送的地址
//发送参数和接受的差不多,但不用定义那么一大堆
Cstring str;
int len;
getDlgItemText(IDC_EDIT_SEND,str);
//将编辑框的文字取出来
wsabuf.len=str.getLength(len); //下面的getbuffer还需要长度……
wsabuf.buf=str.getbuffer(len); //这是难点,将字符串输入buffer,不清楚getbuffer是啥原理。
WSASend(m_sock,&wsabuf,&dwsend,0,(SOCKADDR*)addsend,sizeof(SOCKADDR),NULL,NULL);
setDlgItemText(IDC_EDIT_SEND,"") //用完了把编辑框制空
}
————————————————————————分割线————————————————————————————————
OH~~MY~~GOD!我居然全都默写出来了,而且我感觉都对了,至少可以打85分,哈哈!
哦,对了,前一段时间闲的无聊重新看了遍《棋魂》,看着很爽!
重新下了Tom围棋,去上面对弈,虽然我水平超菜,不过国学经典还是值得品味!