作者在 2008-12-11 22:11:51 发布以下内容
利用CSocket传送大型数据实现
(dlutyuanhongl发表于2005-3-19 16:08:05)
(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);
}
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);
}