学习历程-25岁零基础学编程(4)

继续更新博客。

 

这段时间学的有些慢啊……

 

 

 

接上次的更新,一直在学孙鑫老师的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围棋,去上面对弈,虽然我水平超菜,不过国学经典还是值得品味!

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值