TCP发送文件(转)

//文件传送线程//服务器发送文件,客户端发送文件消息
UINT threadSendFile(LPVOID pvar)
{
    CDlgSendMessage *pDlg = (CDlgSendMessage *) pvar;

CFile m_fSendfile;
m_fSendfile.Close();

if (!m_fSendfile.Open(pDlg->m_sendfilepath, CFile::modeRead | CFile::typeBinary))
{
   AfxMessageBox("打开文件失败!");
   return false;
}


SOCKET sSendMsg;//客户端套接字
SOCKADDR_IN inetAddr;
sSendMsg = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

if (INVALID_SOCKET == sSendMsg)
{
   AfxMessageBox( "创建客户端发送套接字失败!");
   m_fSendfile.Close();
   return 0;
}

inetAddr.sin_family = AF_INET;
inetAddr.sin_port = htons(PUB_MSG_PORT);
inetAddr.sin_addr.s_addr= inet_addr(pDlg->m_receiveip);//为接受文件者IP



  
if (SOCKET_ERROR == connect(sSendMsg, (SOCKADDR *)&inetAddr, sizeof(SOCKADDR_IN)))//为接受文件者
{

         
     AfxMessageBox("对方不在线,不存在监听套接字失败!");
   closesocket(sSendMsg);
   m_fSendfile.Close();
   return 0;
}

char buff[MAX_BUF_SIZE] = "";
CString strMsgSend("1001/");
CString strSize;

//计算文件大小
if (pDlg->m_fiSendFile.nFileSizeLow / (1024 * 1024) != 0)
{
   strSize.Format("%.2fMB", pDlg->m_fiSendFile.nFileSizeLow / (1024.0 * 1024));
}
else
{
   strSize.Format("%.2fKB", pDlg->m_fiSendFile.nFileSizeLow / (1024.0));
}

memcpy(buff, pDlg->m_fiSendFile.szFileTitle, sizeof(pDlg->m_fiSendFile.szFileTitle));
strMsgSend += buff;
strMsgSend += "/";
strMsgSend += strSize;
strMsgSend += "/";
//发送文件标题,文件大小//作为客户端发消息和接受套接字


if (SOCKET_ERROR == send(sSendMsg, strMsgSend.GetBuffer(0), strMsgSend.GetLength(), 0))
{
   AfxMessageBox( "发送消息失败!: threadSendFile");
   closesocket(sSendMsg);
   m_fSendfile.Close();
   return 0;
}

memset(buff, 0, MAX_BUF_SIZE);


if (SOCKET_ERROR == recv(sSendMsg, buff, MAX_BUF_SIZE, 0))//收到对方反馈信息//收到同意接受信息
{
   AfxMessageBox( "接收消息失败!: threadSendFile");
   closesocket(sSendMsg);
   m_fSendfile.Close(); 
   return 0;
}


//解析对方的确认信息
CString strCmd;
strCmd += buff;
strCmd = strCmd.Left(4);
int iCmd = -1;
iCmd = atoi(strCmd);
if (MSG_ACCEPT != iCmd)
{
   AfxMessageBox( "对方拒绝接收文件!: threadSendFile");
   closesocket(sSendMsg);
   m_fSendfile.Close();

   return false;//
}

//对方同意接收文件,开始发送


//创建服务器 发送文件socket, 打开FILE_PORT
SOCKET sSendFile;//监听套接字
SOCKET sAccept;//发送接受套接字
SOCKADDR_IN inetAddrSendFile;
SOCKADDR_IN inetAddrAccept;

sSendFile = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (INVALID_SOCKET == sSendFile)
{
   AfxMessageBox( "创建套接字错误!: threadSendFile");
   closesocket(sSendMsg);
     m_fSendfile.Close();
   return 0;
}

inetAddrSendFile.sin_addr.s_addr = htonl(INADDR_ANY);
inetAddrSendFile.sin_port    = htons(PUB_FILE_PORT);
inetAddrSendFile.sin_family    = AF_INET;

if (SOCKET_ERROR == bind(sSendFile, (SOCKADDR *)&inetAddrSendFile, sizeof(SOCKADDR)))
{
   AfxMessageBox( "绑定套接字错误!: threadSendFile");
   closesocket(sSendMsg);
   closesocket(sSendFile);
   m_fSendfile.Close();
   return 0;
}

if (SOCKET_ERROR == listen(sSendFile, 5))
{
   AfxMessageBox( "监听错误!: threadSendFile");
   closesocket(sSendMsg);
   closesocket(sSendFile);
   m_fSendfile.Close();
   return 0;
}

int iLen = sizeof(SOCKADDR);
sAccept = accept(sSendFile, (SOCKADDR *)&inetAddrAccept, &iLen);

if (INVALID_SOCKET == sAccept)
{
   AfxMessageBox( "accept socket error occurred!: threadSendFile");
   closesocket(sSendMsg);
   closesocket(sSendFile);
   m_fSendfile.Close();
   return 0;
}

//发送文件信息给对方
char buffInfo[MAX_BUF_SIZE] = "";
memcpy(buffInfo, &pDlg->m_fiSendFile, sizeof(pDlg->m_fiSendFile));
send(sAccept, buffInfo, sizeof(pDlg->m_fiSendFile), 0);
memset(buffInfo, 0, MAX_BUF_SIZE);

//对方同意接收huozebujieshou,开始传送
   
    recv(sAccept, buffInfo, MAX_BUF_SIZE, 0);//对方不保持就不往下走

//循环发送文件
DWORD dwRead = 0;
DWORD dwCurrentRead = 0;
BYTE *bReadBuff = new BYTE[MAX_BUF_SIZE];

//设置发送进度


while (dwRead < pDlg->m_fiSendFile.nFileSizeLow)
{ 
   dwCurrentRead = 0;
   memset(bReadBuff, 0, MAX_BUF_SIZE);
   dwCurrentRead = m_fSendfile.Read(bReadBuff, MAX_BUF_SIZE);//读数据到缓冲区
   if (SOCKET_ERROR == send(sAccept, (char *)bReadBuff, dwCurrentRead, 0))//发送数据
   {
    AfxMessageBox( "文件发送中断!: threadSendFile");//如果对方取消持,发送方也也一直往下走
    closesocket(sSendMsg);
    closesocket(sSendFile);
    m_fSendfile.Close();
    break;
   }

   dwRead += dwCurrentRead;//已经发送数据
    CString   str;   
        str.Format("%d",   dwRead);
   AfxMessageBox("已经发送"+str);

}
AfxMessageBox("发送完成");
delete bReadBuff; //释放堆内存
//结束时处理
m_fSendfile.Close();//文件关闭
if (INVALID_SOCKET != sAccept)
{
   closesocket(sAccept);//关闭接受套接字
}
if (INVALID_SOCKET != sSendFile)
{
   closesocket(sSendFile);//关闭发送套接字
}


AfxEndThread(0);

return 1;
}

//客户端文件接收线程
UINT threadRecvFile(LPVOID pvar)
{

    char * m_sip=(char *)pvar;
SOCKET sFileRecv;
SOCKADDR_IN inetAddr;

//新建一个客户socket,连接文件 发送方服务器 接收文件
sFileRecv = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (INVALID_SOCKET == sFileRecv)
{
   AfxMessageBox( "创建套接字失败 : threadRecvFile");
   AfxEndThread(0);
   return 0;
}

inetAddr.sin_family    = AF_INET;
inetAddr.sin_port    = htons(PUB_FILE_PORT);
inetAddr.sin_addr.s_addr = inet_addr(m_sip);


if (SOCKET_ERROR == connect(sFileRecv, (SOCKADDR *)&inetAddr, sizeof(SOCKADDR)))//连接服务器IP
{
   AfxMessageBox("连接对方主机错误 : threadRecvFile");
   closesocket(sFileRecv);
   AfxEndThread(0);
   return 0;
}

//接收文件信息
FileInfo fiRecvFile;

if (SOCKET_ERROR == recv(sFileRecv, (char *)&fiRecvFile, sizeof(FileInfo), 0))
{
   AfxMessageBox("接收文件信息错误 : threadRecvFile");
   closesocket(sFileRecv);
   AfxEndThread(0);
   return 0;
}

CString strFileInfo;
double nfileSize = 0.0;
if (fiRecvFile.nFileSizeLow / (1024 * 1024) != 0)
{
   nfileSize = fiRecvFile.nFileSizeLow / (1024 * 1024);
   strFileInfo.Format("正在接收文件...\n 来自[%s], \n文件名[%s] 大小:[%.2f]MB", 
        inet_ntoa(inetAddr.sin_addr), fiRecvFile.szFileTitle, nfileSize);
}
else
{
   nfileSize = fiRecvFile.nFileSizeLow / (1024);
   strFileInfo.Format("正在接收文件...\n 来自[%s], \n文件名[%s] 大小:[%.2f]KB", 
        inet_ntoa(inetAddr.sin_addr), fiRecvFile.szFileTitle, nfileSize);
}



CFileDialog fdlgSave( FALSE,NULL,fiRecvFile.szFileTitle,
       OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
       _T("所有 (*.*)|*.*|"));

char buff[MAX_BUF_SIZE] = "";
CAcModuleResourceOverride thisResource;
if (fdlgSave.DoModal() != IDOK)
{
  
   sprintf(buff, "%d", MSG_REJECT);
   send(sFileRecv, buff, sizeof(buff), 0);
    closesocket(sFileRecv);//导致发送文件中端
    AfxEndThread(0);
}

CString strFilePath;
strFilePath = fdlgSave.GetPathName();

CFile fRecvedFile(strFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);

DWORD dwTotalRead;
DWORD dwCurrentRead;

dwTotalRead   = 0; //接收总字节
dwCurrentRead = 0; //此次接收字节
BYTE *dataBuff = new BYTE[MAX_BUF_SIZE]; //分配堆内存缓冲

//开始接收
memset(buff, 0, sizeof(buff));
sprintf(buff, "%d", MSG_BEGIN);
send(sFileRecv, buff, sizeof(buff), 0);


while (dwTotalRead < fiRecvFile.nFileSizeLow)
{
   dwCurrentRead = 0;
   memset(dataBuff, 0, MAX_BUF_SIZE);

   dwCurrentRead = recv(sFileRecv, (char *)dataBuff, MAX_BUF_SIZE, 0);
   if (0 == dwCurrentRead || SOCKET_ERROR == dwCurrentRead)
   {
    CString strFileRecvInfo;
    strFileRecvInfo.Format("接收:%s失败!", fiRecvFile.szFileTitle);
  
    break;
   }
   fRecvedFile.Write(dataBuff, dwCurrentRead);
   dwTotalRead += dwCurrentRead;
//   CString str;
//   str.Format("%d",dwTotalRead);
//   AfxMessageBox("已经接受"+str);

   double iCompleted = 0.0;
   iCompleted = (dwTotalRead * 1.0) / fiRecvFile.nFileSizeLow;
   iCompleted *= 10.0;
   CString strSavedInfo;
   strSavedInfo.Format("%d", iCompleted);

}

delete dataBuff; //释放堆内存

CString strFileRecvInfo;
strFileRecvInfo.Format("接收:%s完成!", fiRecvFile.szFileTitle);
AfxMessageBox(strFileRecvInfo);

if (sFileRecv != INVALID_SOCKET)
{
   closesocket(sFileRecv);
}

//关闭文件
fRecvedFile.Close();
//清空文件信息
// memset(&pDlg->m_fiSendFile, 0, sizeof(pDlg->m_fiSendFile));
//
AfxEndThread(0);
return 1;
}  

//服务监听线程//建立服务器模型
UINT threadServer(LPVOID pvar) 
{

SOCKADDR_IN inetAddr;
SOCKADDR_IN inetAccept;
SOCKET sAccept;
SOCKET MySock;
    //服务器监听套接字MYSOCK;


MySock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (INVALID_SOCKET == MySock)
{
   AfxMessageBox( "套接字创建失败!");
   return FALSE;
}

inetAddr.sin_family = AF_INET;
inetAddr.sin_port = htons(PUB_MSG_PORT);   //消息监听端口
//inetAddr.sin_port = 0;
inetAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

//绑定
if (INVALID_SOCKET == bind(MySock, (SOCKADDR *)&inetAddr, sizeof(SOCKADDR)))
{
   AfxMessageBox( "套接字绑定错误 : threadServer!");
   closesocket(MySock);
   return 0;
}

//监听
if (0 != listen(MySock, 5))
{
   AfxMessageBox("套接字监听错误 : threadServer!");
   return 0;
}

//    AfxMessageBox("消息服务启动成功");

//accept
int ilen = sizeof(SOCKADDR_IN);

while(TRUE)
{//服务器会话套接字

   sAccept = accept(MySock, (SOCKADDR *)&inetAccept, &ilen);

   if (INVALID_SOCKET == sAccept)
   {
     AfxMessageBox("接受套接字失败 : threadServer!");
    return 0;
   }
  
   //启动消息处理线程处理新到达的消息
  
   //分配堆内存,存放客户socket信息
   SocketInfo *psInfo = new SocketInfo;
   memset(psInfo, 0, sizeof(SocketInfo));
   psInfo->sNow   = sAccept;
   psInfo->inetAddr = inetAccept;//客户机的地址
  
    AfxBeginThread(threadRecvMsg, (LPVOID)psInfo);
}//while

return 1;
}

//服务器处理 消息处理线程,新消息到达后启动,处理完毕关闭
UINT threadRecvMsg(LPVOID pvar)
{
SocketInfo *psockInfo = (SocketInfo *)pvar;
SocketInfo sockInfo = *psockInfo;
delete psockInfo; //释放堆内存
//每个线程里都有单独的内存,必须释放才能引用,实际上是子线程偷了父线程的内存
  

int iRecv = -1;
char buff[MAX_BUF_SIZE] = "";
char szMsg[256] = "";

//开始接收消息
iRecv = recv(sockInfo.sNow, buff, sizeof(buff), 0);//
if (SOCKET_ERROR == iRecv)
{
   closesocket(sockInfo.sNow);
   AfxMessageBox( "接收消息出错!: threadRecvMsg");
   AfxEndThread(0);
}

//1001/暴风影音2007.exe/32MB/
strcpy(szMsg, buff);
int itype = 0;
CString strTemp;
CString strInMsg;
strTemp += szMsg;
strInMsg += szMsg;
strTemp = strTemp.Left(4);
itype = atoi(strTemp);

//判断是否为文件到达消息
if (MSG_NEW_FILE == itype)
{

   CString strMsgInfo;
   CString strHost;
   CString strFileName;
   CString strSize;
  
   int i, j;
   i = 0;
   j = 0;
   i = strInMsg.Find("/");
   j = strInMsg.Find("/", i + 1);
  
   //取得文件名称
   strFileName = strInMsg.Mid(i + 1, j - i - 1);
   strInMsg.TrimRight("/");
   //取得文件大小
   strSize = strInMsg.Right(strInMsg.GetLength() - strInMsg.ReverseFind('/') - 1);
  
   strMsgInfo.Format("[文件来源:%s]\n[文件名称:%s]\n[文件大小:%s]", inet_ntoa(sockInfo.inetAddr.sin_addr), strFileName, strSize);
   strMsgInfo += "\n同意接收吗?";
   CAcModuleResourceOverride thisResource;
   if (IDYES == MessageBox(NULL, strMsgInfo, "新消息", MB_YESNO))
   {
    char buffSend[MAX_BUF_SIZE] = "";
    char sztemp[20] = "";
    itoa(MSG_ACCEPT, sztemp, 10); 
    strcpy(buffSend, sztemp);
   
    //发送同意接收消息给对方
    if (SOCKET_ERROR == send(sockInfo.sNow, buffSend, sizeof(buffSend), 0))
    {
       AfxMessageBox( "发送消息失败 : threadRecvMsg");
     closesocket(sockInfo.sNow);
     AfxEndThread(0);
    }//if
   
  
    char * senderip;
    senderip=inet_ntoa(sockInfo.inetAddr.sin_addr);
    //启动文件接收线程   
    AfxBeginThread(threadRecvFile, (LPVOID)senderip);
  
   
   }//if
   else
   {
    char buffSend[MAX_BUF_SIZE] = "";
    char sztemp[20] = "";
    itoa(MSG_REJECT, sztemp, 10); 
    strcpy(buffSend, sztemp);
   
    //发送拒绝接收消息给对方
    if (SOCKET_ERROR == send(sockInfo.sNow, buffSend, sizeof(buffSend), 0))
    {
     AfxMessageBox( "发送消息失败 : threadRecvMsg");
     closesocket(sockInfo.sNow);
     AfxEndThread(0);
    }//if
   }//else
  
}//if
else
{
   AfxMessageBox("无法识别的消息");
}//else


return 0;
}

原文地址:https://www.cnblogs.com/lebronjames/p/1793342.html