这是用VC6做,关于网络编程,方面的,一个单文档文件。
有以下文件:
Source Files”有:
    Client.cpp
    ClientDoc.cpp
ClientView,cpp
MainFrm.cpp
MyDirDlg,cpp
SearchDlg,cpp
StdAfx.cppHearder Files有:
Client.h
 ClientDoc.h
ClientView,h
MainFrm.h
MyDirDlg,h
SearchDlg,h
StdAfx.h有以下关键类:
CMainFrame
CmyDirDlg对话框类用,在对话框里显示磁盘信息。
CsearchDlg 对话框类,用于说明对比问题出现的,新建一个类。主要思路以及核心函数及问题所在:
在 CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)  用AfxBeginThread((AFX_THREADPROC)MyThreadLS,this) 启动线程。
MyThreadLS(void *pParam)建立套接字;用Select 模型的方式分两步走,存在可读的套接字,用CMainFrame::Send(SOCKET cSend)函数,存在的可写套接字用BOOL CMainFrame::Recv(SOCKET cRecv)函数。问题出现在,可写套接字用BOOL Recv(SOCKET cRecv)这一支。BOOL CMainFrame:: Recv(SOCKET cRecv)里包括出现问题的,用于接收目录BOOL CMyDirDlg::RecvDirString(int nDataLen,SOCKET s)函数。在BOOL CMainFrame:: Recv(SOCKET cRecv)里,我是用  CMyDirDlg *pCMyDirDlg;
pCMyDirDlg->RecvDirString(nDataLen,s))的方法,把RecvDirString(nDataLen,s))放在在对话框类CmyDirDlg上,在话框类CmyDirDlg上有Tree 控件对应变量为m_Tree 
由于接收到了磁盘目录信息,必需显示出来,在对话框类的CmyDirDlg的RecvDirString(nDataLen,s))函数用Tree控件显示出来。以下是
/*
 * 接收目录包括根目录和显示出来
 */
BOOL CMyDirDlg::RecvDirString(int nDataLen,SOCKET s)
{
CMyDirDlg* pMyDirDlg;
m_TreeCtrl.InsertItem(_T("IP"));

BOOL reVal = TRUE; //返回值
int nReadLen = 0; //接收数据长度
int nTotalLen = 0; //已读数据长度

list<string> listDir; //二级目录链表 listDir.clear(); //清空
string strDir; //二级目录 while ( nTotalLen != nDataLen )
{
char cRecv; //接收字符
SOCKET sClient =s;
nReadLen = recv(sClient, &cRecv, 1,0); //每次接收一个字符
if (SOCKET_ERROR == nReadLen)
{
AfxMessageBox(_T("读取目录失败!"));
reVal = FALSE;
}else if (0 == nReadLen)
{
AfxMessageBox(_T("服务器关闭了连接!"));
reVal = FALSE;
}else if (nReadLen > 0)
{

if ('<' == cRecv) //二级目录的开始分隔符,
{
strDir.erase(strDir.begin(), strDir.end()); //清除数据

}else if ('>' == cRecv) //二级目录的结束分隔符
{
listDir.push_back(strDir); //加入二级目录链表中

}else
{
strDir += cRecv; //添加字符
}
nTotalLen += nReadLen;
}
}//上面部分运行发现都正确,没有什么问题,表明已正确收到信息。 list<string> &listSubDir=listDir;
list<string>::iterator itSubDir = listSubDir.begin();
for (itSubDir; itSubDir != listSubDir.end(); ++itSubDir)
{
//从二级目录链表中取出一个目录(包含了若干三级目录)
string strSubDir = *itSubDir;

string strFind = "\\"; //二级目录与三级目录的分隔符
int rootPos = strSubDir.find(strFind); //找到分隔符位置
if (rootPos != string::npos)
{
//二级目录名称
string strSubDirName = strSubDir.substr(0, rootPos);AfxMessageBox(strSubDirName.c_str());正确能收到磁盘符号。
//调试发现出在 HTREEITEM hti =pMyDirDlg->m_Tree.Ctrl.InsertItem(_T("IP"));

//加入树视的二级节点
// HTREEITEM m_hTreeCur; //m_TreeCtrl  //树的当前子项句柄
// HTREEITEM hChild =pMyDirDlg->m_TreeCtrl.InsertItem(_T(strSubDirName.c_str()), m_hTreeCur,TVI_LAST);
AfxMessageBox(strSubDirName.c_str());

//移动二级目录之后的位置,就是三级目录开始的位置
string::iterator itstr = strSubDir.begin();
int nOffet = 0;
while (nOffet < rootPos +1)
{
itstr++;
nOffet++;
}

//将三级目录加入树视二级节点中
string item;//临时变量,保存三级目录
for (; itstr != strSubDir.end();++itstr)
{
if (SEPERATOR == *itstr)//三级目录分隔符'|'
{
//加入三级目录
// dlg.m_Tree.InsertItem(item.c_str(), hChild, TVI_LAST);
item.erase(item.begin(),item.end());
}else
{
item += *itstr;
}
}

}
//nChild++;//增加二级目录的数量
}
//HTREEITEM m_hTreeCur; //树的当前子项句柄
// dlg->m_tree.Expand(m_hTreeCur,TVE_EXPAND);
listDir.clear(); //清空链表
return true;
}出现的问题话句AfxMessageBox(strSubDirName.c_str());正确能收到磁盘符号。
//调试发现出在 HTREEITEM hti =pMyDirDlg->m_Tree.Ctrl.InsertItem(_T("IP"));
真是想不出,为什么是这样。更不用说了pMyDirDlg->m_TreeCtrl.InsertItem(_T(strSubDirName.c_str()), m_hTreeCur,TVI_LAST);我想知道了上面的问题,后面的好办。
对比发现,如果我把以上所有关键网络函数都放在CsearchDlg对话里用Tree控件显出来,发现没有什么问题,能够正确接收和显示出来。
感谢你们了:
不知道自己有没有把问题说清楚,自己认为可能是类之间传递函数或参数弄错,有什么解决方法,或知道在确的原因,感激不尽。

解决方案 »

  1.   

    看上去像一本书上的例程~
    VisualC++ 网络编程里的介绍select模型例子?
      

  2.   

    大哥,pMyDirDlg没有new出对象,怎么用阿?
      

  3.   

    谢谢这位大哥,认真的看了我的问题。
    我在前面了 CMyDirDlg* pMyDirDlg= new CMyDirDlg; 
    可还是出现同样的问题。
      

  4.   

    pMyDirDlg->m_Tree.Ctrl
    ???中间没有点??
      

  5.   

            //    HTREEITEM        m_hTreeCur;    //m_TreeCtrl                         //树的当前子项句柄
            //    HTREEITEM hChild =pMyDirDlg->m_TreeCtrl.InsertItem(_T(strSubDirName.c_str()), m_hTreeCur,TVI_LAST);  不是你定义为当前就是当前吧.......要
    HTREEITEM hChild =pMyDirDlg->m_TreeCtrl.InsertItem(_T(strSubDirName.c_str()), m_hti,TVI_LAST);  //m_hti是上面的加入的那个...
      

  6.   


    那你pMyDirDlg->Create()了么?
      

  7.   

    对话框对象是个NULL吧?
    new出来
    然后create或者domadol
      

  8.   

    这一句写错了,已在程序中,注释掉了。
    树的控件为m_TreeCtrl,问题是这现在这一句上。
    m_TreeCtrl.InsertItem(_T("IP"));
      

  9.   

    CMyDirDlg *pMyDirDlg = new CMyDirDlg();
      

  10.   

    下面简要写了一下代码,RecvDirString只 接受数据保存到listDir,这个listDir要作为CMyDirDlg 的成员变量
    ,然后在CMyDirDlg::OnInitDialog()调用插入代码BOOL CMainFrame:: Recv(...)
    {
    CMyDirDlg dlg;
    dlg.RecvDirString(...);
    dlg.DoModal();
    } CMyDirDlg::OnInitDialog()
    {
    ...
    //遍历listDir,插到tree
    ...
    }