6 个解决方案
#1
传文件和传普通的数据是一样的。自定义协议,包头+数据内容。包头信息中含有后续将要接收数据的字节的大小
#2
想找个例子看一下数据的处理方式 。邮件地址: ggt87125@163.com
#3
/********************************************************************
created: 2005/12/24
created: 24:12:2005 20:25
modified: 2005/12/24
filename: d:/vcwork/iocomp/iocomp.cpp
file path: d:/vcwork/iocomp
file base: iocomp
file ext: cpp
author: kruglinski(kruglinski_at_gmail_dot_com)
purpose: 利用完成端口技术实现的高性能文件下载服务程序
*********************************************************************/
//#define _WIN32_WINNT 0x0500
#include <stdafx.h>
#include <cstdlib>
#include <clocale>
#include <ctime>
#include <iostream>//一使用输入输出流程序顿时增大70K
#include <vector>
#include <algorithm>
#include <winsock2.h>
#include <mswsock.h>
using namespace std;
#pragma comment(lib,"ws2_32")
#pragma comment(lib,"mswsock")
const int MAX_BUFFER_SIZE=1024;
const int PRE_SEND_SIZE=1024;
const int QUIT_TIME_OUT=3000;
const int PRE_DOT_TIMER=QUIT_TIME_OUT/80;
typedef enum{IoTransFile,IoSend,IoRecv,IoQuit} IO_TYPE;
typedef struct
{
SOCKET hSocket;
SOCKADDR_IN ClientAddr;
}PRE_SOCKET_DATA,*PPRE_SOCKET_DATA;
typedef struct
{
OVERLAPPED oa;
WSABUF DataBuf;
TCHAR Buffer[MAX_BUFFER_SIZE];
IO_TYPE IoType;
}PRE_IO_DATA,*PPRE_IO_DATA;
typedef vector<PPRE_SOCKET_DATA> SocketDataVector;
typedef vector<PPRE_IO_DATA> IoDataVector;
SocketDataVector gSockDataVec;
IoDataVector gIoDataVec;
CRITICAL_SECTION csProtection;
TCHAR * TimeNow(void)
{
time_t t=time(NULL);
tm *localtm=localtime(&t);
static TCHAR timemsg[512]={0};
_tcsftime(timemsg,512,_T("%Z: %B %d %X,%Y"),localtm);
return timemsg;
}
BOOL TransFile(PPRE_IO_DATA pIoData,PPRE_SOCKET_DATA pSocketData,DWORD dwNameLen)
{
//这一句是为nc做的,你可以修改它
pIoData->Buffer[dwNameLen-1]='/0';
HANDLE hFile=CreateFile(pIoData->Buffer,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
BOOL bRet=FALSE;
if(hFile!=INVALID_HANDLE_VALUE)
{
cout<<"Transmit File "<<pIoData->Buffer<<" to client"<<endl;
pIoData->IoType=IoTransFile;
memset(&pIoData->oa,0,sizeof(OVERLAPPED));
*reinterpret_cast<HANDLE*>(pIoData->Buffer)=hFile;
TransmitFile(pSocketData->hSocket,hFile,GetFileSize(hFile,NULL),PRE_SEND_SIZE,reinterpret_cast<LPOVERLAPPED>(pIoData),NULL,TF_USE_SYSTEM_THREAD);
bRet=WSAGetLastError()==WSA_IO_PENDING;
}
else
cout<<"Transmit File "<<"Error:"<<GetLastError()<<endl;
return bRet;
}
DWORD WINAPI ThreadProc(LPVOID IocpHandle)
{
DWORD dwRecv=0;
DWORD dwFlags=0;
HANDLE hIocp=reinterpret_cast<HANDLE>(IocpHandle);
DWORD dwTransCount=0;
PPRE_IO_DATA pPreIoData=NULL;
PPRE_SOCKET_DATA pPreHandleData=NULL;
while(TRUE)
{
if(GetQueuedCompletionStatus(hIocp,&dwTransCount,
reinterpret_cast<LPDWORD>(&pPreHandleData),
reinterpret_cast<LPOVERLAPPED*>(&pPreIoData),INFINITE))
{
if(0==dwTransCount&&IoQuit!=pPreIoData->IoType)
{
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" is closed"<<endl;
closesocket(pPreHandleData->hSocket);
EnterCriticalSection(&csProtection);
IoDataVector::iterator itrIoDelete=find(gIoDataVec.begin(),gIoDataVec.end(),pPreIoData);
SocketDataVector::iterator itrSockDelete=find(gSockDataVec.begin(),gSockDataVec.end(),pPreHandleData);
delete *itrIoDelete;
delete *itrSockDelete;
gIoDataVec.erase(itrIoDelete);
gSockDataVec.erase(itrSockDelete);
LeaveCriticalSection(&csProtection);
continue;
}
switch(pPreIoData->IoType){
case IoTransFile:
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" Transmit finished"<<endl;
CloseHandle(*reinterpret_cast<HANDLE*>(pPreIoData->Buffer));
goto LRERECV;
case IoSend:
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" Send finished"<<endl;
待续。。。。
#4
LRERECV:
pPreIoData->IoType=IoRecv;
pPreIoData->DataBuf.len=MAX_BUFFER_SIZE;
memset(&pPreIoData->oa,0,sizeof(OVERLAPPED));
WSARecv(pPreHandleData->hSocket,&pPreIoData->DataBuf,1,
&dwRecv,&dwFlags,
reinterpret_cast<LPWSAOVERLAPPED>(pPreIoData),NULL);
break;
case IoRecv:
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" recv finished"<<endl;
pPreIoData->IoType=IoSend;
if(!TransFile(pPreIoData,pPreHandleData,dwTransCount))
{
memset(&pPreIoData->oa,0,sizeof(OVERLAPPED));
strcpy(pPreIoData->DataBuf.buf,"File transmit error!/r/n");
pPreIoData->DataBuf.len=strlen(pPreIoData->DataBuf.buf);
WSASend(pPreHandleData->hSocket,&pPreIoData->DataBuf,1,
&dwRecv,dwFlags,
reinterpret_cast<LPWSAOVERLAPPED>(pPreIoData),NULL);
}
break;
case IoQuit:
goto LQUIT;
default:
;
}
}
}
LQUIT:
return 0;
}
HANDLE hIocp=NULL;
SOCKET hListen=NULL;
BOOL WINAPI ShutdownHandler(DWORD dwCtrlType)
{
PRE_SOCKET_DATA PreSockData={0};
PRE_IO_DATA PreIoData={0};
PreIoData.IoType=IoQuit;
if(hIocp)
{
PostQueuedCompletionStatus(hIocp,1,
reinterpret_cast<ULONG_PTR>(&PreSockData),
reinterpret_cast<LPOVERLAPPED>(&PreIoData));
cout<<"Shutdown at "<<TimeNow()<<endl<<"wait for a moment please"<<endl;
用vs2005以上编译器进行编译
#5
好的谢谢 有没有 客户端上传到服务器的方式吗?
#6
这里 pIoData->Buffer 是客户端发送的文件名称吗? 如果文件过大TransmitFile会一次性发送?
#1
传文件和传普通的数据是一样的。自定义协议,包头+数据内容。包头信息中含有后续将要接收数据的字节的大小
#2
想找个例子看一下数据的处理方式 。邮件地址: ggt87125@163.com
#3
/********************************************************************
created: 2005/12/24
created: 24:12:2005 20:25
modified: 2005/12/24
filename: d:/vcwork/iocomp/iocomp.cpp
file path: d:/vcwork/iocomp
file base: iocomp
file ext: cpp
author: kruglinski(kruglinski_at_gmail_dot_com)
purpose: 利用完成端口技术实现的高性能文件下载服务程序
*********************************************************************/
//#define _WIN32_WINNT 0x0500
#include <stdafx.h>
#include <cstdlib>
#include <clocale>
#include <ctime>
#include <iostream>//一使用输入输出流程序顿时增大70K
#include <vector>
#include <algorithm>
#include <winsock2.h>
#include <mswsock.h>
using namespace std;
#pragma comment(lib,"ws2_32")
#pragma comment(lib,"mswsock")
const int MAX_BUFFER_SIZE=1024;
const int PRE_SEND_SIZE=1024;
const int QUIT_TIME_OUT=3000;
const int PRE_DOT_TIMER=QUIT_TIME_OUT/80;
typedef enum{IoTransFile,IoSend,IoRecv,IoQuit} IO_TYPE;
typedef struct
{
SOCKET hSocket;
SOCKADDR_IN ClientAddr;
}PRE_SOCKET_DATA,*PPRE_SOCKET_DATA;
typedef struct
{
OVERLAPPED oa;
WSABUF DataBuf;
TCHAR Buffer[MAX_BUFFER_SIZE];
IO_TYPE IoType;
}PRE_IO_DATA,*PPRE_IO_DATA;
typedef vector<PPRE_SOCKET_DATA> SocketDataVector;
typedef vector<PPRE_IO_DATA> IoDataVector;
SocketDataVector gSockDataVec;
IoDataVector gIoDataVec;
CRITICAL_SECTION csProtection;
TCHAR * TimeNow(void)
{
time_t t=time(NULL);
tm *localtm=localtime(&t);
static TCHAR timemsg[512]={0};
_tcsftime(timemsg,512,_T("%Z: %B %d %X,%Y"),localtm);
return timemsg;
}
BOOL TransFile(PPRE_IO_DATA pIoData,PPRE_SOCKET_DATA pSocketData,DWORD dwNameLen)
{
//这一句是为nc做的,你可以修改它
pIoData->Buffer[dwNameLen-1]='/0';
HANDLE hFile=CreateFile(pIoData->Buffer,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
BOOL bRet=FALSE;
if(hFile!=INVALID_HANDLE_VALUE)
{
cout<<"Transmit File "<<pIoData->Buffer<<" to client"<<endl;
pIoData->IoType=IoTransFile;
memset(&pIoData->oa,0,sizeof(OVERLAPPED));
*reinterpret_cast<HANDLE*>(pIoData->Buffer)=hFile;
TransmitFile(pSocketData->hSocket,hFile,GetFileSize(hFile,NULL),PRE_SEND_SIZE,reinterpret_cast<LPOVERLAPPED>(pIoData),NULL,TF_USE_SYSTEM_THREAD);
bRet=WSAGetLastError()==WSA_IO_PENDING;
}
else
cout<<"Transmit File "<<"Error:"<<GetLastError()<<endl;
return bRet;
}
DWORD WINAPI ThreadProc(LPVOID IocpHandle)
{
DWORD dwRecv=0;
DWORD dwFlags=0;
HANDLE hIocp=reinterpret_cast<HANDLE>(IocpHandle);
DWORD dwTransCount=0;
PPRE_IO_DATA pPreIoData=NULL;
PPRE_SOCKET_DATA pPreHandleData=NULL;
while(TRUE)
{
if(GetQueuedCompletionStatus(hIocp,&dwTransCount,
reinterpret_cast<LPDWORD>(&pPreHandleData),
reinterpret_cast<LPOVERLAPPED*>(&pPreIoData),INFINITE))
{
if(0==dwTransCount&&IoQuit!=pPreIoData->IoType)
{
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" is closed"<<endl;
closesocket(pPreHandleData->hSocket);
EnterCriticalSection(&csProtection);
IoDataVector::iterator itrIoDelete=find(gIoDataVec.begin(),gIoDataVec.end(),pPreIoData);
SocketDataVector::iterator itrSockDelete=find(gSockDataVec.begin(),gSockDataVec.end(),pPreHandleData);
delete *itrIoDelete;
delete *itrSockDelete;
gIoDataVec.erase(itrIoDelete);
gSockDataVec.erase(itrSockDelete);
LeaveCriticalSection(&csProtection);
continue;
}
switch(pPreIoData->IoType){
case IoTransFile:
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" Transmit finished"<<endl;
CloseHandle(*reinterpret_cast<HANDLE*>(pPreIoData->Buffer));
goto LRERECV;
case IoSend:
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" Send finished"<<endl;
待续。。。。
#4
LRERECV:
pPreIoData->IoType=IoRecv;
pPreIoData->DataBuf.len=MAX_BUFFER_SIZE;
memset(&pPreIoData->oa,0,sizeof(OVERLAPPED));
WSARecv(pPreHandleData->hSocket,&pPreIoData->DataBuf,1,
&dwRecv,&dwFlags,
reinterpret_cast<LPWSAOVERLAPPED>(pPreIoData),NULL);
break;
case IoRecv:
cout<<"Client:"
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<":"<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<" recv finished"<<endl;
pPreIoData->IoType=IoSend;
if(!TransFile(pPreIoData,pPreHandleData,dwTransCount))
{
memset(&pPreIoData->oa,0,sizeof(OVERLAPPED));
strcpy(pPreIoData->DataBuf.buf,"File transmit error!/r/n");
pPreIoData->DataBuf.len=strlen(pPreIoData->DataBuf.buf);
WSASend(pPreHandleData->hSocket,&pPreIoData->DataBuf,1,
&dwRecv,dwFlags,
reinterpret_cast<LPWSAOVERLAPPED>(pPreIoData),NULL);
}
break;
case IoQuit:
goto LQUIT;
default:
;
}
}
}
LQUIT:
return 0;
}
HANDLE hIocp=NULL;
SOCKET hListen=NULL;
BOOL WINAPI ShutdownHandler(DWORD dwCtrlType)
{
PRE_SOCKET_DATA PreSockData={0};
PRE_IO_DATA PreIoData={0};
PreIoData.IoType=IoQuit;
if(hIocp)
{
PostQueuedCompletionStatus(hIocp,1,
reinterpret_cast<ULONG_PTR>(&PreSockData),
reinterpret_cast<LPOVERLAPPED>(&PreIoData));
cout<<"Shutdown at "<<TimeNow()<<endl<<"wait for a moment please"<<endl;
用vs2005以上编译器进行编译
#5
好的谢谢 有没有 客户端上传到服务器的方式吗?
#6
这里 pIoData->Buffer 是客户端发送的文件名称吗? 如果文件过大TransmitFile会一次性发送?