18,356
社区成员
发帖
与我相关
我的任务
分享
// 得到文件尺寸
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);///MSDN;
__int64 persize = 2097151;//2G-1(每次发送的大小)
LARGE_INTEGER li;
li.QuadPart = 0;
li.LowPart = SetFilePointer (hFile, li.LowPart,&li.HighPart, MoveMethod);
while (true)
{
if (qwFileSize > persize)//大于2G-1
{
TransmitFile(sClient, hFile,persize,1024, (LPOVERLAPPED)li.QuadPart,NULL,TF_REUSE_SOCKET|TF_DISCONNECT);
li.QuadPart += persize;
li.LowPart = SetFilePointer (hFile, li.LowPart,&li.HighPart, MoveMethod);
size -= persize;
}
else
{
TransmitFile(sClient, hFile,size,1024,(LPOVERLAPPED)li.QuadPart,NULL,TF_REUSE_SOCKET|TF_DISCONNECT);
break;
}
}
CloseHandle(hFile);
方法2:使用文件映射方式处理文件, 然后逐块调用WSASend:
代码省略, 我现在用的老婆的电脑, 木有编译器, 文件映射的代码可以参考我写的一个例子:
http://download.csdn.net/detail/wumn29/5179452
DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort=(HANDLE)CompletionPortID;
DWORD dwBytesTransferred;
SOCKET sClient;
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
while (TRUE)
{
GetQueuedCompletionStatus(
CompletionPort,
&dwBytesTransferred,
(PULONG_PTR)&sClient,
(LPOVERLAPPED *)&lpPerIOData,
INFINITE);
if (dwBytesTransferred == 0xFFFFFFFF)
{
return 0;
}
if (lpPerIOData->OperationType == RECV_POSTED)
{
if (dwBytesTransferred == 0)
{
// Connection was closed by client
printf("Connection was closed by client\r\n");
closesocket(sClient);
HeapFree(GetProcessHeap(), 0, lpPerIOData);
}
else
{
printf("IP:%s PORT:%s DATA:%s\r\n", lpPerIOData->szHeader, (char*)(lpPerIOData->szHeader)+strlen(lpPerIOData->szHeader)+1, lpPerIOData->szMessage);
char* answer = "服务器收到了请求, 现在开始传送文件...";
send(sClient, answer, strlen(answer), 0);
HANDLE hFile = CreateFileA("C:\\Documents and Settings\\wangwei_b\\My Documents\\Visual Studio 2008\\Projects\\完成端口\\Release\\测试文件传输.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
int size = GetFileSize(hFile, NULL);
FILE* pfile = (File*)SetFilePointer(hFile, 0, 0, FILE_BEGIN);
__int64 persize = 2097151;//2G-1
while (true)
{
if (size > persize)//大于2G-1
{
TransmitFile(sClient, hFile,persize,1024, (LPOVERLAPPED)pfile,NULL,TF_REUSE_SOCKET|TF_DISCONNECT);
pfile += persize;
size -= persize;
}
else
{
TransmitFile(sClient, hFile,size,1024,(LPOVERLAPPED)pfile,NULL,TF_REUSE_SOCKET|TF_DISCONNECT);
}
}
CloseHandle(hFile);
// Launch another asynchronous operation for sClient
memset(lpPerIOData->szMessage, 0, sizeof(lpPerIOData->szMessage));
lpPerIOData->Buffer.len = MSGSIZE;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->OperationType = RECV_POSTED;
WSARecv(sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
NULL);
//printf("工作线程WSARecv, lpPerIOData->Buffer=%s\r\n", lpPerIOData->Buffer);
}
}
}
return 0;
}
DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort=(HANDLE)CompletionPortID;
DWORD dwBytesTransferred;
SOCKET sClient;
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
while (TRUE)
{
GetQueuedCompletionStatus(
CompletionPort,
&dwBytesTransferred,
(PULONG_PTR)&sClient,
(LPOVERLAPPED *)&lpPerIOData,
INFINITE);
if (dwBytesTransferred == 0xFFFFFFFF)
{
return 0;
}
if (lpPerIOData->OperationType == RECV_POSTED)
{
if (dwBytesTransferred == 0)
{
// Connection was closed by client
printf("Connection was closed by client\r\n");
closesocket(sClient);
HeapFree(GetProcessHeap(), 0, lpPerIOData);
}
else
{
printf("IP:%s PORT:%s DATA:%s\r\n", lpPerIOData->szHeader, (char*)(lpPerIOData->szHeader)+strlen(lpPerIOData->szHeader)+1, lpPerIOData->szMessage);
char* answer = "服务器收到了请求, 现在开始传送文件...";
send(sClient, answer, strlen(answer), 0);
HANDLE hFile = CreateFileA("C:\\Documents and Settings\\wangwei_b\\My Documents\\Visual Studio 2008\\Projects\\完成端口\\Release\\测试文件传输.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
TransmitFile(sClient, hFile,0,1024,NULL,NULL,TF_REUSE_SOCKET|TF_DISCONNECT);
CloseHandle(hFile);
// Launch another asynchronous operation for sClient
memset(lpPerIOData->szMessage, 0, sizeof(lpPerIOData->szMessage));
lpPerIOData->Buffer.len = MSGSIZE;
lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
lpPerIOData->OperationType = RECV_POSTED;
WSARecv(sClient,
&lpPerIOData->Buffer,
1,
&lpPerIOData->NumberOfBytesRecvd,
&lpPerIOData->Flags,
&lpPerIOData->overlap,
NULL);
//printf("工作线程WSARecv, lpPerIOData->Buffer=%s\r\n", lpPerIOData->Buffer);
}
}
}
return 0;
}