用CSocket传输文件
问题有以下三个:
1,传不了大文件
2,接收跟发送里面的Sleep(1)一旦去掉就无法正常传输,导致传输速度如龟
3,接收方还没确定传输方的进度条已经开始走了....监听线程UINT FileListenThread(LPVOID lparam)
{
CIPMsgDlg *pDlg=(CIPMsgDlg *)lparam;
CSocket sockSrvr; pDlg->m_Port=PORT;
int createSucceed=sockSrvr.Create(pDlg->m_Port);
if(createSucceed==0)
{
AfxMessageBox("Listen Create错误!");
return -1;
}

int listenSucceed=sockSrvr.Listen(); //开始监听
if(listenSucceed==0)
{
AfxMessageBox("Listen Listen错误!");
return -1;
}

CSocket *recSo=new CSocket;
SOCKADDR_IN *addrRecv=new SOCKADDR_IN;
int iAddrSize=sizeof(SOCKADDR_IN);

int acceptSucceed=sockSrvr.Accept(*recSo,(SOCKADDR *)addrRecv,&iAddrSize);
if(acceptSucceed==0)
{
AfxMessageBox("Listen Accept错误!");
return -1;
}
sockSrvr.Close();
char flag[2]={0};
if(recSo->Receive(flag,2)!=2) 
{
return -1;
}
if(strcmp(flag,"D")==0)
{
delete recSo;
recSo=NULL;
delete addrRecv;
addrRecv=NULL;
sockSrvr.Close();
return 999;
}
sockSrvr.Close();
g_pThreadLisen=::AfxBeginThread(FileListenThread,pDlg);
//这里将打开一个带有进度条的对话框,接收线程在该对话框里面创建
pDlg->ReceiveFile(recSo,addrRecv);
return 0;

}发送线程UINT SendFileThread(LPVOID lparam)
{

CIPMsgDlg *pDlg=(CIPMsgDlg *)lparam;
CSocket sockClient;
sockClient.Create();
CString ip;
ip=pDlg->m_StrSendAddr;
sockClient.Connect(ip, PORT);  int end=0;
end=sockClient.Send("F",2);

if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThread Send错误!");
return -1;
}

else if(end!=2) 
{
AfxMessageBox("文件头错误");
return -1;
}
///////////////////////////////////////////////////////////////////
CFile myFile;
FileInfo myFileInfo;
if(!myFile.Open(pDlg->m_StrSendFileName, CFile::modeRead | CFile::typeBinary))
return -1;
myFileInfo.iFileLength=myFile.GetLength();
strcpy(myFileInfo.szFileName,myFile.GetFileName());

sockClient.Send(&myFileInfo,sizeof(myFileInfo));

pDlg->m_progress.SetRange32(0,myFileInfo.iFileLength);

myFile.Seek(0,CFile::begin);
char *pBuf=new char[8096];
memset(pBuf,0,8096);
CString strError;
int num=0;
end=0;
int temp=0;
for(;;)
{
num=myFile.Read(pBuf, 8096);
if(num==0) 
break;
end=sockClient.Send(pBuf, num); 
temp+=end;
pDlg->m_progress.SetPos(temp);
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThread Send错误!");
break;

}
Sleep(1);
}

CSocket sockTmp;
int createSucceed=sockTmp.Create(PORT+100);
if(createSucceed==0)
{
AfxMessageBox("Listen Create错误!");
return -1;
}

int listenSucceed=sockTmp.Listen(); //开始监听
if(listenSucceed==0)
{
AfxMessageBox("Listen Listen错误!");
return -1;
}

  CSocket So;
  SOCKADDR_IN addrAccept;
  int iAddrSize=sizeof(SOCKADDR_IN);

int acceptSucceed=sockTmp.Accept(So,(SOCKADDR *)&addrAccept,&iAddrSize); if(temp==myFileInfo.iFileLength)
AfxMessageBox("文件发送成功");
else 
AfxMessageBox("文件发送失败"); myFile.Close(); delete []pBuf;
pBuf=NULL; pDlg->GetDlgItem(IDC_BTN_STOP_SEND)->EnableWindow(FALSE);//
return 0;
}接收线程,创建于弹出的对话框内UINT ReceiveFileThread(LPVOID lpParam)
{ CRecvFileDlg *pDlg=(CRecvFileDlg *)lpParam; CFileDialog dlg(false); //


char fileme[500]={0};
strcpy(fileme,pDlg->m_StrFileName.GetBuffer(0));
dlg.m_ofn.lpstrFile=fileme;
if(dlg.DoModal()==IDOK)
{
pDlg->m_StrFileName=dlg.GetPathName();
pDlg->m_progress.ShowWindow(SW_SHOW);
}
else
{
pDlg->SendMessage(WM_CLOSE,0,0);
return -101;

}
//char buf[4096]={0};
char *pBuf=new char[8096];
memset(pBuf,0,8096);
CFile f(pDlg->m_StrFileName,
CFile::modeCreate|CFile::modeWrite); //存文件

pDlg->m_progress.SetRange32(0,pDlg->m_iLengSize);

int n=0; //接受的字节数 0表示结束
int temp=0;
pDlg->GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(true);
int i=0;

for(;;)
{
n=pDlg->m_pSock->Receive(pBuf,8096);
if(n<8096)
{
f.Write(pBuf,n);
temp+=n;
break;
}
f.Write(pBuf,n);
temp+=n;
pDlg->m_progress.SetPos(temp);

if(pDlg->m_stopWork) 
{
pDlg->m_stopWork=false;
break ;
}  Sleep(1); }
f.Close();
pDlg->m_progress.SetPos(0);
CString strAddr=inet_ntoa(pDlg->m_pAddr->sin_addr);
CSocket sockTmp;
sockTmp.Create();
sockTmp.Connect(strAddr,PORT+100); if(temp==pDlg->m_iLengSize)
AfxMessageBox("文件接收成功");
else
AfxMessageBox("文件接收失败");

pDlg->SendMessage(WM_CLOSE);
return 101;
}求高手指点,十万火急.....小弟先在此感谢各位了

解决方案 »

  1.   

    直接用c的socket啊,在msdn里面找下就好了,写过几个TCP和UDP程序都是用它的。msdn里面有很详细的例程。
    SendFileThread里面怎们没有指定是TCP还是UDP,不是connect就一定是TCP的,UDP也有connect的。你创建socket的时候没有用指定方式,估计系统就默认是UDP方式了吧。所以你发送的时候,对方都未确认接收就开始发送了,因为UDP只是把数据包传出去就完事了。
      

  2.   

    如果没有Sleep(1),发送和接收又是非阻塞的,那么CPU资源都将被循环耗掉。
      

  3.   

    用Csocket跨线程有些问题的,即使能成功也会速度变慢
    另外接收要在onreceive中完成,不要主动去调用receive
      

  4.   

    代码没有仔细看,不过这几个问题估计不难问题有以下三个: 
    1,传不了大文件 
    ---- 这个和传小文件有什么区别?无论多大的文件你都是一个数据包一个数据包的传的
    这里要注意的是new出来的buffer注意释放,不要导致内存泄漏就行了。2,接收跟发送里面的Sleep(1)一旦去掉就无法正常传输,导致传输速度如龟 
    ----- 这个去掉会有什么问题呢?导致cpu 100%吗?3,接收方还没确定传输方的进度条已经开始走了....
    ----- 这个传输的双方确定一个握手协议就不会有这样的问题了。-----------------------
    另外,建议你将界面和网络层的分离开来。发送或者接受一个包的时候向界面发一个消息让其自己更新就行了。一般用到socket的很少用CSocket,自己写的话比较好控制,并且注意一下io模型就行了。
      

  5.   

    用TCP传文件源代码:
    http://download.csdn.net/source/888667
      

  6.   

    1,传不了大文件
    //这个问题应该不大,估计是下面两个问题之一引起的
    2,接收跟发送里面的Sleep(1)一旦去掉就无法正常传输,导致传输速度如龟
    //不要去掉,去掉后会导致接收或发送时独占cpu,影响多线程编码
    3,接收方还没确定传输方的进度条已经开始走了....
    //如果想等接收方确定,进度条才走,可以用setsocketopt(好像是这个吧),设置发送方缓存为0,这样数据就不会放到缓存而是立刻发送到对方
      

  7.   

    http://download.csdn.net/source/1830896我的问题代码传于此....