【转自】http://blog.csdn.net/firebird321/article/details/2417168
服务端
#include "StdAfx.h"
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <winsock2.h>
#include <string>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
using namespace boost;
#define PORT 4567
#define DATA_BUFSIZE 1000
#define FileName "c://test.rar"
typedef struct tagPER_HANDLE_DATA
{
SOCKET Socket;
sockaddr_in addr;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
//单I/O操作数据
typedef struct tagPER_IO_DATA
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
int BufferLen;
int OperationType; //读写标志
}PER_IO_DATA, *LPPER_IO_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
int main(int argc,char * argv[])
{
HANDLE CompletionPort;
WSADATA wsd;
SYSTEM_INFO SystemInfo;
SOCKADDR_IN InternetAddr;
SOCKET Listen;
int err=WSAStartup(MAKEWORD(2, 2), &wsd);
if (err == SOCKET_ERROR)
{
cout << "Init Socket error..." << endl;
return -1;
}
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
GetSystemInfo(&SystemInfo);
for (int i = 0; i < (int)SystemInfo.dwNumberOfProcessors; ++i)
{
HANDLE ThreadHandle;
ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,NULL);
CloseHandle(ThreadHandle);
}
Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
InternetAddr.sin_family = PF_INET;
InternetAddr.sin_port = htons(PORT);
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
err=bind(Listen, (SOCKADDR*)&InternetAddr, sizeof(InternetAddr));
if (err<0)
{
cout << "Bind socket error..." << endl;
WSACleanup();
return -1;
}
listen(Listen, 200);
DWORD RecvBytes = 0;
DWORD Flags = 0;
while (TRUE)
{
PER_HANDLE_DATA * PerHandleData = NULL;
SOCKADDR_IN saRemote;
SOCKET Accept;
int RemoteLen;
RemoteLen = sizeof(saRemote);
Accept = accept(Listen, (SOCKADDR*)&saRemote, &RemoteLen);
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
cout << "Socket number " << Accept << " connected" << endl;
PerHandleData->Socket = Accept; //Socket
PerHandleData->addr=saRemote; //对方地址
//将接收套接字和完成端口关联起来
CreateIoCompletionPort((HANDLE)Accept,CompletionPort,(DWORD)PerHandleData,0);
// 单I/O操作数据
LPPER_IO_DATA PerIoData = NULL;
PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = 0; //投递第一个请求
WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
return 0;
}
DWORD WINAPI ServerWorkerThread(LPVOID lpParam)
{
HANDLE CompletionPort = (HANDLE)lpParam;
DWORD BytesTransferred;
LPOVERLAPPED lpOverlapped;
LPPER_HANDLE_DATA PerHandleData = NULL;
LPPER_IO_DATA PerIoData = NULL;
DWORD RecvBytes;
DWORD Flags=0;
BOOL bRet = FALSE;
//文件信息
HANDLE hFile;
hFile = ::CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
cout << "需要发送的文件不存在" << endl;
return 0;
}
//存放到内存中
//取得文件大小(字节)
DWORD dwLen = GetFileSize(hFile, NULL);
char *readBuf = new char[dwLen];
memset(readBuf, 0, dwLen);
DWORD dwReadLen;
//将文件内容存放到 readBuf 中。然后将 readBuf 中的内容发送给客户端 加载到内存
ReadFile(hFile, readBuf, dwLen, &dwReadLen, NULL);
while (TRUE)
{
bRet = GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(PULONG_PTR)&PerHandleData,(LPOVERLAPPED*)&lpOverlapped,INFINITE);
PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(lpOverlapped, PER_IO_DATA,Overlapped);
if (BytesTransferred == 0)
{
cout << "Socket number " << PerHandleData->Socket << " closed" << endl;
shutdown(PerHandleData->Socket,SD_BOTH);
closesocket(PerHandleData->Socket);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
//数据处理成功了!这儿就收到了来自客户端的数据
//这里暂时注释,除非作为聊天程序才启用
//cout <<"Socket: " << PerHandleData->Socket << " Says:" << PerIoData->DataBuf.buf << endl;
if (dwLen > 0)
{
//发送文件长度给客户端(应该把文件名也发过去)
if(strcmp( PerIoData->DataBuf.buf, "ready" )==0)
{
string sLen = boost::lexical_cast<string>(dwLen);
send(PerHandleData->Socket, sLen.c_str() ,strlen(sLen.c_str()) + 1, 0);
}
//发送第一块数据给客户端
else if (strcmp( PerIoData->DataBuf.buf, "go" )==0)
{
int nBufSize = 0;
if (dwLen > DATA_BUFSIZE)
{
nBufSize = DATA_BUFSIZE;
}
else
{
nBufSize = dwLen;
}
char *pBuf = new char[nBufSize];
memset(pBuf, 0, nBufSize);
MoveMemory(pBuf, readBuf, nBufSize);
//cout << "第一块数据内容: " << endl << pBuf << endl;
//Sleep(10000);
send(PerHandleData->Socket, pBuf ,nBufSize, 0);
dwLen -= nBufSize;
delete pBuf;
}
//继续发送剩余的文件
else
{
int nBufSize = 0;
if (dwLen > DATA_BUFSIZE)
{
nBufSize = DATA_BUFSIZE;
}
else
{
nBufSize = dwLen;
}
char *pBuf = new char[nBufSize];
memset(pBuf, 0, nBufSize);
string sLen = PerIoData->DataBuf.buf;
int nLen = boost::lexical_cast<int>(sLen);
MoveMemory(pBuf, readBuf+(nLen-1)*DATA_BUFSIZE, nBufSize);
//cout << pBuf << endl;
send(PerHandleData->Socket, pBuf ,nBufSize, 0);
dwLen -= nBufSize;
delete pBuf;
}
}
//为下一个重叠调用建立单I/O操作数据
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = 0; // read
WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
delete readBuf;
return 0;
}
客户端
#include <iostream>
#include <Winsock2.h>
#include <boost/lexical_cast.hpp>
#include <string>
#pragma comment(lib, "ws2_32.lib")
#include "stdio.h"
using namespace std;
using namespace boost;
#define PORT 4567
#define DATA_BUFSIZE 1000
#define FileName "d://test.rar"
void main()
{
//初始化socket编程环境
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
}
//建立客户端socket
SOCKET sockClient = socket( AF_INET ,SOCK_STREAM , 0 ) ;
//服务器地址
SOCKADDR_IN addrSrv ;
//addrSrv.sin_addr.S_un.S_addr = inet_addr("124.130.50.137") ;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1") ;
addrSrv.sin_family = AF_INET ;
addrSrv.sin_port = htons( 4567 ) ;
//连接服务器
connect( sockClient , (SOCKADDR*)&addrSrv , sizeof(SOCKADDR)) ;
//告诉服务端准备开始接收文件
send(sockClient, "ready", strlen("ready")+1, 0);
//接收文件的长度
char cFileLen[100] = {0};
recv( sockClient , cFileLen , 100 , 0 ) ;
int nLast = 0;
int nLen = atoi(cFileLen);
DWORD dwSize = 0;
//开辟一个内存,接收文件内容,然后写到硬盘上
char *pRecvBuf = new char[nLen+1];
memset(pRecvBuf, 1, nLen+1);
//第一次要包,是需要得到服务器发送的第二块数据,所以 iCount = 1
int iCount = 1;
//告诉服务端准备开始接收文件
send(sockClient, "go", strlen("go")+1, 0);
while(1)
{
if (0 == nLen)
break;
int nBufSize = 0;
if (nLen > DATA_BUFSIZE)
{
nBufSize = DATA_BUFSIZE;
}
else
{
nBufSize = nLen;
}
char *recvBuf = new char[nBufSize];
memset(recvBuf, 1, nBufSize);
int rev = recv( sockClient , recvBuf , nBufSize, 0 ) ;
dwSize += rev;
MoveMemory(pRecvBuf+(iCount-1)*DATA_BUFSIZE, recvBuf, nBufSize);
iCount++;
string strCount = boost::lexical_cast<string>(iCount);
if (nLen > DATA_BUFSIZE)
//nLast = nLen;
send(sockClient, strCount.c_str(), strlen(strCount.c_str())+1, 0);
nLen -= nBufSize;
delete recvBuf;
}
DeleteFile(FileName);
HANDLE hFile;
hFile = ::CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
cout << "创建或打开文件时失败" << endl;
closesocket( sockClient ) ;
WSACleanup() ;
return;
}
//这里开始写文件
DWORD dwWritenSize = 0;
nLen = atoi(cFileLen);
WriteFile(hFile, pRecvBuf, nLen, &dwWritenSize, NULL);
FlushFileBuffers(hFile);
delete pRecvBuf;
CloseHandle(hFile);
system("pause");
closesocket( sockClient ) ;
WSACleanup() ;
}
#include "StdAfx.h"
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <winsock2.h>
#include <string>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
using namespace boost;
#define PORT 4567
#define DATA_BUFSIZE 1000
#define FileName "c://test.rar"
typedef struct tagPER_HANDLE_DATA
{
SOCKET Socket;
sockaddr_in addr;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
//单I/O操作数据
typedef struct tagPER_IO_DATA
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
int BufferLen;
int OperationType; //读写标志
}PER_IO_DATA, *LPPER_IO_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
int main(int argc,char * argv[])
{
HANDLE CompletionPort;
WSADATA wsd;
SYSTEM_INFO SystemInfo;
SOCKADDR_IN InternetAddr;
SOCKET Listen;
int err=WSAStartup(MAKEWORD(2, 2), &wsd);
if (err == SOCKET_ERROR)
{
cout << "Init Socket error..." << endl;
return -1;
}
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
GetSystemInfo(&SystemInfo);
for (int i = 0; i < (int)SystemInfo.dwNumberOfProcessors; ++i)
{
HANDLE ThreadHandle;
ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,NULL);
CloseHandle(ThreadHandle);
}
Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
InternetAddr.sin_family = PF_INET;
InternetAddr.sin_port = htons(PORT);
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
err=bind(Listen, (SOCKADDR*)&InternetAddr, sizeof(InternetAddr));
if (err<0)
{
cout << "Bind socket error..." << endl;
WSACleanup();
return -1;
}
listen(Listen, 200);
DWORD RecvBytes = 0;
DWORD Flags = 0;
while (TRUE)
{
PER_HANDLE_DATA * PerHandleData = NULL;
SOCKADDR_IN saRemote;
SOCKET Accept;
int RemoteLen;
RemoteLen = sizeof(saRemote);
Accept = accept(Listen, (SOCKADDR*)&saRemote, &RemoteLen);
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
cout << "Socket number " << Accept << " connected" << endl;
PerHandleData->Socket = Accept; //Socket
PerHandleData->addr=saRemote; //对方地址
//将接收套接字和完成端口关联起来
CreateIoCompletionPort((HANDLE)Accept,CompletionPort,(DWORD)PerHandleData,0);
// 单I/O操作数据
LPPER_IO_DATA PerIoData = NULL;
PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = 0; //投递第一个请求
WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
return 0;
}
DWORD WINAPI ServerWorkerThread(LPVOID lpParam)
{
HANDLE CompletionPort = (HANDLE)lpParam;
DWORD BytesTransferred;
LPOVERLAPPED lpOverlapped;
LPPER_HANDLE_DATA PerHandleData = NULL;
LPPER_IO_DATA PerIoData = NULL;
DWORD RecvBytes;
DWORD Flags=0;
BOOL bRet = FALSE;
//文件信息
HANDLE hFile;
hFile = ::CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
cout << "需要发送的文件不存在" << endl;
return 0;
}
//存放到内存中
//取得文件大小(字节)
DWORD dwLen = GetFileSize(hFile, NULL);
char *readBuf = new char[dwLen];
memset(readBuf, 0, dwLen);
DWORD dwReadLen;
//将文件内容存放到 readBuf 中。然后将 readBuf 中的内容发送给客户端 加载到内存
ReadFile(hFile, readBuf, dwLen, &dwReadLen, NULL);
while (TRUE)
{
bRet = GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(PULONG_PTR)&PerHandleData,(LPOVERLAPPED*)&lpOverlapped,INFINITE);
PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(lpOverlapped, PER_IO_DATA,Overlapped);
if (BytesTransferred == 0)
{
cout << "Socket number " << PerHandleData->Socket << " closed" << endl;
shutdown(PerHandleData->Socket,SD_BOTH);
closesocket(PerHandleData->Socket);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
//数据处理成功了!这儿就收到了来自客户端的数据
//这里暂时注释,除非作为聊天程序才启用
//cout <<"Socket: " << PerHandleData->Socket << " Says:" << PerIoData->DataBuf.buf << endl;
if (dwLen > 0)
{
//发送文件长度给客户端(应该把文件名也发过去)
if(strcmp( PerIoData->DataBuf.buf, "ready" )==0)
{
string sLen = boost::lexical_cast<string>(dwLen);
send(PerHandleData->Socket, sLen.c_str() ,strlen(sLen.c_str()) + 1, 0);
}
//发送第一块数据给客户端
else if (strcmp( PerIoData->DataBuf.buf, "go" )==0)
{
int nBufSize = 0;
if (dwLen > DATA_BUFSIZE)
{
nBufSize = DATA_BUFSIZE;
}
else
{
nBufSize = dwLen;
}
char *pBuf = new char[nBufSize];
memset(pBuf, 0, nBufSize);
MoveMemory(pBuf, readBuf, nBufSize);
//cout << "第一块数据内容: " << endl << pBuf << endl;
//Sleep(10000);
send(PerHandleData->Socket, pBuf ,nBufSize, 0);
dwLen -= nBufSize;
delete pBuf;
}
//继续发送剩余的文件
else
{
int nBufSize = 0;
if (dwLen > DATA_BUFSIZE)
{
nBufSize = DATA_BUFSIZE;
}
else
{
nBufSize = dwLen;
}
char *pBuf = new char[nBufSize];
memset(pBuf, 0, nBufSize);
string sLen = PerIoData->DataBuf.buf;
int nLen = boost::lexical_cast<int>(sLen);
MoveMemory(pBuf, readBuf+(nLen-1)*DATA_BUFSIZE, nBufSize);
//cout << pBuf << endl;
send(PerHandleData->Socket, pBuf ,nBufSize, 0);
dwLen -= nBufSize;
delete pBuf;
}
}
//为下一个重叠调用建立单I/O操作数据
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATA_BUFSIZE;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = 0; // read
WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
delete readBuf;
return 0;
}
客户端
#include <iostream>
#include <Winsock2.h>
#include <boost/lexical_cast.hpp>
#include <string>
#pragma comment(lib, "ws2_32.lib")
#include "stdio.h"
using namespace std;
using namespace boost;
#define PORT 4567
#define DATA_BUFSIZE 1000
#define FileName "d://test.rar"
void main()
{
//初始化socket编程环境
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
}
//建立客户端socket
SOCKET sockClient = socket( AF_INET ,SOCK_STREAM , 0 ) ;
//服务器地址
SOCKADDR_IN addrSrv ;
//addrSrv.sin_addr.S_un.S_addr = inet_addr("124.130.50.137") ;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1") ;
addrSrv.sin_family = AF_INET ;
addrSrv.sin_port = htons( 4567 ) ;
//连接服务器
connect( sockClient , (SOCKADDR*)&addrSrv , sizeof(SOCKADDR)) ;
//告诉服务端准备开始接收文件
send(sockClient, "ready", strlen("ready")+1, 0);
//接收文件的长度
char cFileLen[100] = {0};
recv( sockClient , cFileLen , 100 , 0 ) ;
int nLast = 0;
int nLen = atoi(cFileLen);
DWORD dwSize = 0;
//开辟一个内存,接收文件内容,然后写到硬盘上
char *pRecvBuf = new char[nLen+1];
memset(pRecvBuf, 1, nLen+1);
//第一次要包,是需要得到服务器发送的第二块数据,所以 iCount = 1
int iCount = 1;
//告诉服务端准备开始接收文件
send(sockClient, "go", strlen("go")+1, 0);
while(1)
{
if (0 == nLen)
break;
int nBufSize = 0;
if (nLen > DATA_BUFSIZE)
{
nBufSize = DATA_BUFSIZE;
}
else
{
nBufSize = nLen;
}
char *recvBuf = new char[nBufSize];
memset(recvBuf, 1, nBufSize);
int rev = recv( sockClient , recvBuf , nBufSize, 0 ) ;
dwSize += rev;
MoveMemory(pRecvBuf+(iCount-1)*DATA_BUFSIZE, recvBuf, nBufSize);
iCount++;
string strCount = boost::lexical_cast<string>(iCount);
if (nLen > DATA_BUFSIZE)
//nLast = nLen;
send(sockClient, strCount.c_str(), strlen(strCount.c_str())+1, 0);
nLen -= nBufSize;
delete recvBuf;
}
DeleteFile(FileName);
HANDLE hFile;
hFile = ::CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
cout << "创建或打开文件时失败" << endl;
closesocket( sockClient ) ;
WSACleanup() ;
return;
}
//这里开始写文件
DWORD dwWritenSize = 0;
nLen = atoi(cFileLen);
WriteFile(hFile, pRecvBuf, nLen, &dwWritenSize, NULL);
FlushFileBuffers(hFile);
delete pRecvBuf;
CloseHandle(hFile);
system("pause");
closesocket( sockClient ) ;
WSACleanup() ;
}

4458

被折叠的 条评论
为什么被折叠?



