用 VC+socket 传输大文件

在这个程序中,客户端读取桌面的一个 1.48 GB (1,597,701,030 字节) 的RAR文件发送给服务器。因为这里仅用于学习,所以客户端要连接的目标地址使用127.0.0.1。服务器端接将收的文件文件保存在C盘根目录下。

为保证程序的可靠发送,程序采用TCP协议。经过反复试验得出结论,程序中的重中之重是双方的 ReadFile 和 WriteFile。相反 recv 和 send 不是重要的。为了使代码尽量简化,程序去掉所有错误检查,只让服务器端的accept函数提示一下有人发起连接。双方收发完文件之后直接退出程序。

//服务器端

#include<iostream>
#include<Windows.h>
using namespace std;
const int iBufferSize = 1024*1024;
char buffer[iBufferSize];
void main()
{
	WSAData data;
	WSAStartup(MAKEWORD(2,2),&data);
	SOCKET s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	SOCKADDR_IN addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8888);
	addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	bind(s1, (SOCKADDR*)&addr, sizeof(addr));
	listen(s1, 5);
	int len = sizeof(addr);
	SOCKET s2 = accept(s1, (SOCKADDR*)&addr, & len);
	if(s2!=INVALID_SOCKET)
		cout<<" accept right"<<endl;

	LARGE_INTEGER i64FileSize, i64FileSizeCopy;
	recv(s2, (char*)&i64FileSize.QuadPart, sizeof(i64FileSize.QuadPart), 0);
	i64FileSizeCopy = i64FileSize;

	HANDLE hFile = CreateFile(L"c:\\a.rar", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);

	while( i64FileSize.QuadPart >0 )
	{
		ZeroMemory(buffer, iBufferSize);
		int size;
		size = recv(s2, buffer, iBufferSize, 0);

		DWORD dwNumBytes;
		while( TRUE )
		{
			if( i64FileSize.QuadPart < size )
				size = i64FileSize.QuadPart;
			WriteFile(hFile, buffer, size, &dwNumBytes, 0);
			i64FileSize.QuadPart -= dwNumBytes;
			if( dwNumBytes < size )
				size -= dwNumBytes;
			else
				break;
		}
	}
}


 

//客户端

#include<iostream>
#include<Windows.h>
using namespace std;

const int iBufferSize = 1024*1024;
char buffer[iBufferSize];

void main()
{
	WSAData data;
	WSAStartup(MAKEWORD(2,2),&data);
	SOCKET s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	SOCKADDR_IN addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8888);
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	connect(s1, (SOCKADDR*)&addr, sizeof(addr));

	HANDLE hFile = CreateFile(L"C:\\Users\\ys\\Desktop\\Visual C++开发入行真功夫光盘二次.rar",
		GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);
	LARGE_INTEGER i64FileSize, i64FileSizeCopy;
	GetFileSizeEx(hFile, &i64FileSize);
	i64FileSizeCopy = i64FileSize;
	
	send(s1, (char*)&i64FileSize, sizeof(LARGE_INTEGER),0);

	while( i64FileSize.QuadPart > 0 )
	{
		DWORD dwNumBytes, dwNumberToRead = iBufferSize;
		while(TRUE)
		{
			if( i64FileSize.QuadPart <= dwNumberToRead )
				dwNumberToRead = i64FileSize.QuadPart;
			ReadFile(hFile, buffer, dwNumberToRead, &dwNumBytes, 0);
			i64FileSize.QuadPart -= dwNumBytes;
			if( dwNumBytes < dwNumberToRead )
				dwNumberToRead -= dwNumBytes;
			else
				break;
		}

		send(s1, buffer, iBufferSize, 0);

		cout<<"已发送 "
			<< (i64FileSizeCopy.QuadPart - i64FileSize.QuadPart)				<<"B "
			<< (i64FileSizeCopy.QuadPart - i64FileSize.QuadPart)/1024			<<"K "
			<< (i64FileSizeCopy.QuadPart - i64FileSize.QuadPart)/1024/1024		<<"M "
			<< (i64FileSizeCopy.QuadPart - i64FileSize.QuadPart)/1024/1024/1024 <<"G"<<endl;
	}
}


 

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值