我需要用一种传统的网络接口NetBIOS编写两台计算机通信的程序,我的发送部分基本没有什么问题,可接收出现了不少的问题:
第一个问题:程序接收数据时,只能正确接收一次。第二次发送不同的数据时,接收文本框没有任何变化。
第二个问题:在对话框中再任意添加一个文本框,通过向导给这个文本框添加一个值变量(CString类型),其他地方不给这个变量赋任何值,但当程序第一次运行时这个文本框也能显示发送的数据。
请各位高手看看,到底是怎么会事?现将主要代码贴出来:
==============相关变量类型和结构定义========
struct ZFS {char text[20];};
struct ZFS Buffer;//[50];  //缓冲
int p_Buffer_In,p_Buffer_Out; //缓冲指针
CString ReceiveBuffer;
==============发送数据函数==================
bool CNetBios::Send(CString callname,CString *SendData,int len)
{
  bool result=false;
  if(ncbnum)
  {
     ZeroMemory(&ncb,sizeof(NCB));
 //memset((char*)&ncb,0,sizeof(NCB));
     ncb.ncb_command=NCBDGSEND;       //同步数据报发送
     ncb.ncb_num=ncbnum;
     ncb.ncb_buffer=(unsigned char*)(LPCTSTR)SendData;
     ncb.ncb_length=len;  
     memcpy(ncb.ncb_callname,callname,strlen(callname));
     ncb.ncb_lana_num=uselana;
     if(Netbios(&ncb)==NRC_GOODRET)
     {
         result=true;
     }
   }
   return result;
}
===============发送按钮函数==================
void CCNetBiosDlg::OnSendButton5() 
{   UpdateData(TRUE);
if(SendBios.Send(m_starget,m_stext,sizeof(ZFS))==true) 
{
m_slabel="数据已经发出";
}
else
m_slabel="发送有误";
UpdateData(FALSE);
    
}
====================接收函数====================
bool CNetBios::Receive(void  (CALLBACK *ncb_post)(NCB *))
{
       bool result=false;
       if(ncbnum)
       {
 memset(&ncb,0,sizeof(NCB));
        ncb.ncb_command=NCBDGRECV|ASYNCH;//异步接收
        ncb.ncb_num=ncbnum;//
        ncb.ncb_buffer=(unsigned char*)(LPCTSTR)ReceiveBuffer;
 //CString ReceiveBuffer;
        ncb.ncb_length=50;  //类中设置的接收缓冲区的大小 
 ncb.ncb_post=ncb_post;
        ncb.ncb_lana_num=uselana;
        if(Netbios(&ncb)==NRC_GOODRET)
            result=true;
       }
       return result;
}
这里用了个回调函数,这个回调函数是:
CCNetBiosDlg *BiosDlg;//因为RecPostProgram(pn)是对话框类的成员函数,所以//就声明了这个全局变量
void  __stdcall Post(NCB * pn)  //POST例程
{
    BiosDlg->RecPostProgram(pn);//调用CCNetBiosDlg对象中的处理函数
}
================RecPostProgram(pn)======================
void  CCNetBiosDlg::RecPostProgram(NCB *ncb)

  struct ZFS *recdata;
  if(ncb->ncb_length==sizeof(ZFS))
  {
     recdata=(struct ZFS *)ncb->ncb_buffer; //将接收缓冲区指针转为结构指针
     Buffer[p_Buffer_In]=*recdata;//将数据复制至缓冲
  p_Buffer_In++;               //接收缓冲指针移动
     if(p_Buffer_In==50)     
        p_Buffer_In=0;
  }
  PostMessage(WM_MESSAGE,0,0); //产生一个消息
  RecBios.Receive(&Post);         //继续接收过程,首次调用Receive(&Post)
//函数是在NetBIOS成功注册返回以后。
 }
============自定义消息函数===================
void  __fastcall CCNetBiosDlg::UseMessage(UINT uMsg) 
{  
   while(p_Buffer_In!=p_Buffer_Out) //如有新的数据则执行如下程序
   {     
m_sreceive=Buffer[p_Buffer_Out].text;//m_sreceive是用来接收显示数据
//的文本框变量
       p_Buffer_Out++;               //读取缓冲指针移动
       if(p_Buffer_Out==50)
         p_Buffer_Out=0;
   }
}
这个程序是参考一个用C++ Build6开发且能正确运行的程序改写到VC6的。改写过程中很不顺利,开始根本不能接收数据,后来通过试的方法发现是有些参数类型不对,如ncb.ncb_buffer=(unsigned char*)(LPCTSTR)ReceiveBuffer;不能写成ncb.ncb_buffer=(unsigned char*)ReceiveBuffer;或ncb.ncb_buffer=ReceiveBuffer;再如:CString ReceiveBuffer;不能该为char ReceiveBuffer [50];否则程序就第一次运行都不能接收到数据。
还有,单步调试时程序运行到回调函数的recdata=(struct ZFS *)ncb->ncb_buffer;这句就不向下运行,自定义消息根本没有运行,真是奇怪及了!!

解决方案 »

  1.   

    我估计原因是你使用的ReceiveBuffer是自动变量(使用栈内存),而接收方式又是异步的,也就是Netbios(&ncb)函数将信息注册到接收队列后就返回了;此时Netbios接收事件还没有被触发,而Receive()函数体也就结束了,此时ReceiveBuffer栈内存自动被释放,而当RecPostProgram()函数被激活时,ncb->ncb_buffer指向的已经是无效内存区了,故程序卡死在这里。
       如果是这样,你只需在Receive中new一块堆内存来接收数据,然后由RecPostProgram()函数负责使用完ncb->ncb_buffer指针后释放它。
      

  2.   

    TO:scaton(scaton)
    要怎么写代码?能否给一个参考?