谁能给一个IOCP服务器端接收文件的例子呢?

时间:2022-08-28 23:37:30
谁能给一个IOCP服务器端接收文件的例子呢 ? 客户端向服务器端发送文件.

6 个解决方案

#1


引用楼主 ggt87125 的回复:
谁能给一个IOCP服务器端接收文件的例子呢 ? 客户端向服务器端发送文件.

传文件和传普通的数据是一样的。自定义协议,包头+数据内容。包头信息中含有后续将要接收数据的字节的大小

#2


引用 1 楼 visualeleven 的回复:
引用楼主 ggt87125 的回复:
谁能给一个IOCP服务器端接收文件的例子呢 ? 客户端向服务器端发送文件.

传文件和传普通的数据是一样的。自定义协议,包头+数据内容。包头信息中含有后续将要接收数据的字节的大小


 想找个例子看一下数据的处理方式 。邮件地址: 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


引用 4 楼 gameslq 的回复:
C/C++ code

LRERECV:
                 pPreIoData->IoType=IoRecv;
                 pPreIoData->DataBuf.len=MAX_BUFFER_SIZE;
                 memset(&amp;pPreIoData->oa,0,sizeof(OVERLAPPED));

       ……


好的谢谢  有没有 客户端上传到服务器的方式吗?

#6


引用 4 楼 gameslq 的回复:
C/C++ code

LRERECV:
                 pPreIoData->IoType=IoRecv;
                 pPreIoData->DataBuf.len=MAX_BUFFER_SIZE;
                 memset(&amp;pPreIoData->oa,0,sizeof(OVERLAPPED));

       ……


 这里 pIoData->Buffer 是客户端发送的文件名称吗? 如果文件过大TransmitFile会一次性发送?
     

#1


引用楼主 ggt87125 的回复:
谁能给一个IOCP服务器端接收文件的例子呢 ? 客户端向服务器端发送文件.

传文件和传普通的数据是一样的。自定义协议,包头+数据内容。包头信息中含有后续将要接收数据的字节的大小

#2


引用 1 楼 visualeleven 的回复:
引用楼主 ggt87125 的回复:
谁能给一个IOCP服务器端接收文件的例子呢 ? 客户端向服务器端发送文件.

传文件和传普通的数据是一样的。自定义协议,包头+数据内容。包头信息中含有后续将要接收数据的字节的大小


 想找个例子看一下数据的处理方式 。邮件地址: 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


引用 4 楼 gameslq 的回复:
C/C++ code

LRERECV:
                 pPreIoData->IoType=IoRecv;
                 pPreIoData->DataBuf.len=MAX_BUFFER_SIZE;
                 memset(&amp;pPreIoData->oa,0,sizeof(OVERLAPPED));

       ……


好的谢谢  有没有 客户端上传到服务器的方式吗?

#6


引用 4 楼 gameslq 的回复:
C/C++ code

LRERECV:
                 pPreIoData->IoType=IoRecv;
                 pPreIoData->DataBuf.len=MAX_BUFFER_SIZE;
                 memset(&amp;pPreIoData->oa,0,sizeof(OVERLAPPED));

       ……


 这里 pIoData->Buffer 是客户端发送的文件名称吗? 如果文件过大TransmitFile会一次性发送?