利用CSocket传送大型数据实现

作者在 2008-12-11 22:11:51 发布以下内容
                        利用CSocket传送大型数据实现
                           (dlutyuanhongl发表于2005-3-19 16:08:05)
传输大型文件实列

        SOCKET API,98/NT/2000调试通过。

C/S均建立读/写线程,一但连接,C/S便都可发送/接收文件,发送文件方式使用字节流传送。将传送文件进行分割,每次传送1K,CLIENT或SERVER方收到后进行重组。接收文件方式使用异步SOCKET,根据实际读入数据写文件。在LAN上测试,C/S多次相互传输大型文件如:IIS,SQL SP,和几个上百M的文件效果良好。

Server.cpp

//---------------------------------------------------------------------------
//  SERVER端
//  
//  贾佳,jiasys@21cn.com
//---------------------------------------------------------------------------

#include <vcl.h>
#include <winsock.h>
#define  BUFFSIZE 1024
#pragma hdrstop

#include "Server.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

WSADATA wsaData;
SOCKET  sck,sc;
SOCKADDR_IN to,client;
BOOL flag=TRUE;
int iAddrSize,ret,ret_no,i=0;
TCHAR szBuf[BUFFSIZE];
fd_set FdRead;

//---------------------------------------------------------------------------
//  ReadClient
//
//  接收文件数据线程,判断建立文件关键字,每次将实际读到的数据写入文件。
//
//---------------------------------------------------------------------------

DWORD WINAPI ReadClient(LPVOID lPort)
{
   HANDLE  hFile=NULL;
   DWORD   dwWrite,dwFileSize;
   TCHAR   szFileName[MAX_PATH];

   FD_ZERO(&FdRead);
   FD_SET(sck,&FdRead);

   while(TRUE)
   {
     ret_no=select(0,&FdRead,NULL,NULL,NULL);
     if(ret_no==SOCKET_ERROR)
     {
       closesocket(sck);
       return FALSE;
     }

    if(FD_ISSET(sck,&FdRead))
    {
       iAddrSize=sizeof(client);
       sc=accept(sck,(SOCKADDR *)&client,&iAddrSize);
       if(sc==INVALID_SOCKET)
       {
          MessageBox(NULL,"accept error",NULL,MB_OK);
          closesocket(sc);
          WSACleanup();
       }
      getpeername(sck,(SOCKADDR *)&client,&iAddrSize);
      ShowMessage(inet_ntoa(client.sin_addr));
     FD_SET(sc,&FdRead);
    }

    if(FD_ISSET(sc,&FdRead))
    {
      ZeroMemory(szBuf,sizeof(szBuf));
      if((dwFileSize=recv(sc,szBuf,BUFFSIZE,0))==SOCKET_ERROR)
      {
         closesocket(sc);
         CloseHandle(hFile);
         return FALSE;
      }
      else if((strncmp(szBuf,"UPFILE_",lstrlen("UPFILE_")))==0)
      {
       wsprintf(szFileName,"c:\%s",szBuf);
       hFile=CreateFile(szFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,
                       NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL|
                       FILE_ATTRIBUTE_ARCHIVE,(HANDLE)NULL);

       if(hFile==INVALID_HANDLE_VALUE)
       {
          MessageBox(NULL,"Server Open File Error",NULL,MB_OK);
          return FALSE;
       }
       ZeroMemory(szBuf,sizeof(szBuf));
      }
     else
      WriteFile(hFile,szBuf,dwFileSize,&dwWrite,NULL);
    }
   }
CloseHandle(hFile);
return TRUE;
}

//---------------------------------------------------------------------------
//  WriteClient
//
//  发送文件数据线程,每次预读1K数据,根据实际读取发送,直到读取数据小于1K
//
//---------------------------------------------------------------------------

DWORD WINAPI WriteClient(LPVOID szFileName)
{

  HANDLE       hFile;
  DWORD        dwRead,dwNdx;
  BOOL         bRet;
  TCHAR        szFileBuff[BUFFSIZE],szSend[MAX_PATH];

  wsprintf(szSend,"DOWNFILE_%s",ExtractFileName((LPCTSTR)szFileName).c_str());
  send(sc,szSend,lstrlen(szSend),0);
  hFile=CreateFile((LPCTSTR)szFileName,GENERIC_READ|GENERIC_WRITE,
                    FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL|
                    FILE_ATTRIBUTE_ARCHIVE,(HANDLE)NULL);

    if(hFile==INVALID_HANDLE_VALUE)
    {
      MessageBox(NULL,"Open File Error",NULL,MB_OK);
      ExitProcess(0);
    }

    do
    {
      bRet=ReadFile(hFile,szFileBuff,BUFFSIZE,&dwRead,NULL);
      if(bRet==FALSE)
      {
        MessageBox(NULL,"Read Buf ERROR!",NULL,MB_OK);
        break;
      }
      else if(dwRead==0)
      {
        MessageBox(NULL,"File EOF!",NULL,MB_OK);
        break;
      }
      else
      {
       send(sc,szFileBuff,dwRead,0);
      }
    }while(dwRead==BUFFSIZE);

  CloseHandle(hFile);
return TRUE;
}

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{

  HANDLE  hThread;
  DWORD   dwTid;

  if(WSAStartup(MAKEWORD(1,1),&wsaData)!=NULL)
  {
    ShowMessage("初始化WINSOCK错误");
    WSACleanup();
  }

  if((sck=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)
  {
      ShowMessage("SOCKET错误");
      closesocket(sck);
      WSACleanup();
  }

  to.sin_family=AF_INET;
  to.sin_port=htons(926);
  to.sin_addr.s_addr=htonl(INADDR_ANY);

  if(setsockopt(sck,SOL_SOCKET,SO_REUSEADDR,(LPSTR)&flag,sizeof(flag))==SOCKET_ERROR)
  {
      ShowMessage("setsockopt error!");
      closesocket(sck);
  }


  if(bind(sck,(struct sockaddr *)&to,sizeof(to))==SOCKET_ERROR)
  {
      ShowMessage("Could not bind");
      closesocket(sck);
  }

  else
  {
    listen(sck,1);
    hThread=CreateThread(NULL,0,ReadClient,(LPVOID)0,0,&dwTid);
    CloseHandle(hThread);
  }

}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE  hThread;
DWORD   dwTid;

if(OpenDialog1->Execute())
{
   hThread=CreateThread(NULL,0,WriteClient,(LPVOID)OpenDialog1->FileName.c_str(),0,&dwTid);
   CloseHandle(hThread);
}


}
//---------------------------------------------------------------------------

Client.cpp

//---------------------------------------------------------------------------
//  CLIENT端
//
//  贾佳,jiasys@21cn.com
//---------------------------------------------------------------------------

#include <vcl.h>
#include <winsock.h>
#define  BUFFSIZE 1024
#pragma hdrstop

#include "Client.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

WSADATA wsa;
SOCKET sck;
SOCKADDR_IN tto;
hostent *host;
fd_set FdRead;
int port=926,ret,i;
DWORD dwRead;


//---------------------------------------------------------------------------
//  ReadClient
//
//  接收文件数据线程,判断建立文件关键字,每次将实际读到的数据写入文件。
//
//---------------------------------------------------------------------------

DWORD WINAPI ReadClient(LPVOID lParam)
{
HANDLE  hFile;
DWORD   dwWrite,dwFileSize;
TCHAR   szFileName[MAX_PATH];
TCHAR   szBuff[BUFFSIZE];

  FD_ZERO(&FdRead);
  FD_SET(sck,&FdRead);

  while(TRUE)
  {
    ret=select(0,&FdRead,NULL,NULL,NULL);
    if(ret==SOCKET_ERROR)
    {
      closesocket(sck);
      return FALSE;
    }
    else if(FD_ISSET(sck,&FdRead))
    {
      ZeroMemory(szBuff,sizeof(szBuff));
      if((dwFileSize=recv(sck,szBuff,BUFFSIZE,0))==SOCKET_ERROR)
      {
         closesocket(sck);
         CloseHandle(hFile);
         return FALSE;
      }
      else if((strncmp(szBuff,"DOWNFILE_",lstrlen("DOWNFILE_")))==0)
      {
       wsprintf(szFileName,"c:\%s",szBuff);
       hFile=CreateFile(szFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,
                       NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL|
                       FILE_ATTRIBUTE_ARCHIVE,(HANDLE)NULL);

       if(hFile==INVALID_HANDLE_VALUE)
       {
          MessageBox(NULL,"Cli Open File Error",NULL,MB_OK);
          return FALSE;
       }
       ZeroMemory(szBuff,sizeof(szBuff));
      }
     else
      WriteFile(hFile,szBuff,dwFileSize,&dwWrite,NULL);
    }
  }
return TRUE;
}

//---------------------------------------------------------------------------
//  WriteClient
//
//  发送文件数据线程,每次预读1K数据,根据实际读取发送,直到读取数据小于1K
//
//---------------------------------------------------------------------------


DWORD WINAPI WriteClient(LPVOID szFileName)
{
  HANDLE       hFile;
  DWORD        dwRead,dwNdx;
  BOOL         bRet;
  TCHAR        szFileBuff[BUFFSIZE],szSend[MAX_PATH];

  wsprintf(szSend,"UPFILE_%s",ExtractFileName((LPCTSTR)szFileName).c_str());
  send(sck,szSend,lstrlen(szSend),0);
  hFile=CreateFile((LPCTSTR)szFileName,GENERIC_READ|GENERIC_WRITE,
                    FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL|
                    FILE_ATTRIBUTE_ARCHIVE,(HANDLE)NULL);

   if(hFile==INVALID_HANDLE_VALUE)                        
   {
      MessageBox(NULL,"Open File Error",NULL,MB_OK);
      ExitProcess(0);
   }

    do
    {
      bRet=ReadFile(hFile,szFileBuff,BUFFSIZE,&dwRead,NULL);
      if(bRet==FALSE)
      {
        MessageBox(NULL,"Read Buf ERROR!",NULL,MB_OK);
        break;
      }
      else if(dwRead==0)
      {
        MessageBox(NULL,"File EOF!",NULL,MB_OK);
        break;
      }
      else
      {
       send(sck,szFileBuff,dwRead,0);
      }
    }while(dwRead==BUFFSIZE);

  CloseHandle(hFile);
return TRUE;
}

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE  hThread;
DWORD   dwTid;

WSAStartup(MAKEWORD(1,1),&wsa);
sck=socket(AF_INET,SOCK_STREAM,0);

if(sck==INVALID_SOCKET)
{
   ShowMessage("Could not create a sock");
   ExitProcess(0);
}

else
{
     host=gethostbyname(Edit1->Text.c_str());
     tto.sin_family=AF_INET;
     tto.sin_port=htons(port);
     CopyMemory(&tto.sin_addr,host->h_addr,host->h_length);
     if((connect(sck,(struct sockaddr FAR *)&tto,sizeof(tto))==SOCKET_ERROR))
     {
          ShowMessage("connect error!");
          closesocket(sck);
     }

     else
     {
        hThread=CreateThread(NULL,0,ReadClient,(LPVOID)0,0,&dwTid);
        CloseHandle(hThread);
     }
  }

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
HANDLE  hThread;
DWORD   dwTid;

if(OpenDialog1->Execute())
{
   hThread=CreateThread(NULL,0,WriteClient,(LPVOID)OpenDialog1->FileName.c_str(),0,&dwTid);
   CloseHandle(hThread);
}
windows网络编程 | 阅读 4113 次
文章评论,共0条
游客请输入验证码