想弄个传文件程序。
服务器先启动,等待接收文件,客户端后启动用来发送文件。双方用TCP连接好之后客户端先发送一个 LARGE_INTEGER 变量,变量中保存的是文件的大小。这个文件是光盘的压缩文件,右键属性显示1.48G。
发送完大小之后双方开始用 while 循环发送和接收,程序运行了大概20秒之后,双方都各自阻塞在自己的 recv 函数。下面客户端发送完文件大小之后,服务器就进入 while 循环开始接收数据,把收到的数据写入文件,在给客户 send 回去 WriteFile 了多少字节, 客户端收到服务器 WriteFile 多少字节之后调用文件的 SetFilePointerEx,以便下次从那继续发送下面是服务器端和客户端的代码和运行结果图
//服务器端(接收文件)#include<Windows.h>
#include<iostream>
using namespace std;const int iOneMBufferSize = 1024*1024;
char buffer[iOneMBufferSize];//一兆空间
void main()
{
setlocale(LC_ALL, "chs");
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,100);
int len = sizeof(addr);
SOCKET s2 = accept(s1,(SOCKADDR*) &addr,&len);
if( s2 != INVALID_SOCKET )
wcout<<L"***** 有客户端连入 *****"<<endl; LARGE_INTEGER i64FileSize, i64FileSizeCopy;
recv(s2,(char*)&i64FileSize, sizeof(i64FileSize), 0);
i64FileSizeCopy.QuadPart = i64FileSize.QuadPart;
wcout<<L"**** 文件大小是 "<< i64FileSize.QuadPart <<L"字节, 文件保存在C盘根目录下 ****"<<endl;
HANDLE hFile = CreateFile(L"C:\\接收文件.rar",
GENERIC_READ | GENERIC_WRITE,//读写权限
0,//不共享
0,//默认安全描述符
OPEN_ALWAYS,//存在就打开,不存在就创建
0,//Flags and Attributes
0);//hFileTemplate
if(hFile==INVALID_HANDLE_VALUE)
wcout<<L"**** 文件创建失败 ****"<<endl;
DWORD dwNumBytes;
while( i64FileSize.QuadPart>0)//这里的一堆wcout是为看出阻塞在哪
{
ZeroMemory(buffer, iOneMBufferSize);
wcout<<L"服务器准备接收文件"<<endl;
int size = recv(s2, buffer, iOneMBufferSize, 0);
wcout<<L"服务器收完文件"<<endl;
wcout<<L"服务器准写文件"<<endl;
WriteFile(hFile, buffer, size, &dwNumBytes, 0);
wcout<<L"服务器写完文件"<<endl; wcout<<L"服务器准备发送 dwNumBytes"<<endl;
send(s2, (char*)&dwNumBytes, sizeof(DWORD), 0);
wcout<<L"服务器发完 dwNumBytes"<<endl; i64FileSize.QuadPart -= dwNumBytes; // wcout<<L"接收中\t";
}
wcout<<endl<<L"****接收完毕****"<<endl;
while(1)
{}
}//客户端(发送文件)
#include<Windows.h>
#include<iostream>
using namespace std;const int iOneMBufferSize = 1024*1024;
char buffer[iOneMBufferSize];//一兆空间
void main()
{
setlocale(LC_ALL, "chs");
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);
char ip[100];
ZeroMemory(ip,100);
wcout<<L"输入对方IP: ";
cin>>ip;//这里输入 127.0.0.1
addr.sin_addr.S_un.S_addr = inet_addr(ip);
int e = connect(s1, (SOCKADDR*)&addr, sizeof(addr));
if(e==-1)
wcout<<L"connect 函数失败"<<endl; HANDLE hFile = CreateFile(L"C:\\Users\\ys\\Desktop\\Visual C++开发入行真功夫光盘二次.rar",
GENERIC_READ | GENERIC_WRITE,//读写权限
0,//不共享
0,//默认安全描述符
OPEN_ALWAYS ,//存在就打开,不存在就创建
0,//Flags and Attributes
0);//hFileTemplate
if(hFile==INVALID_HANDLE_VALUE)
wcout<<L"**** 文件读取失败 ****"<<endl; LARGE_INTEGER i64FileSize, i64FileSizeCopy;
GetFileSizeEx(hFile, &i64FileSize);
i64FileSizeCopy.QuadPart = i64FileSize.QuadPart;
wcout<<L"共需发送 " << i64FileSize.QuadPart <<L"字节" <<endl;
send(s1, (char*)&i64FileSize.QuadPart, sizeof(i64FileSize.QuadPart), 0);
DWORD dwNumBytes; while( i64FileSize.QuadPart >0 )//这里的一堆wcout是为看出阻塞在哪
{
ZeroMemory(buffer, iOneMBufferSize);
wcout<<L"客户端准备读文件"<<endl;
ReadFile(hFile, buffer, iOneMBufferSize, &dwNumBytes, 0);
wcout<<L"客户端读完文件"<<endl;
wcout<<L"客户端准备发送文件"<<endl;
send(s1, buffer, dwNumBytes, 0);
wcout<<L"客户端发完文件"<<endl; DWORD size;
wcout<<L"客户端准备接收服务器返回的 dwNumBytes"<<endl;
recv(s1, (char*)&size, sizeof(DWORD), 0);
wcout<<L"客户端收完服务器返回的 dwNumBytes"<<endl; LARGE_INTEGER move;
move.QuadPart = size;
wcout<<L"客户端准备设置文件指针"<<endl;
SetFilePointerEx(hFile, move, 0, FILE_CURRENT);
wcout<<L"客户端设完文件指针"<<endl;
i64FileSize.QuadPart -= size; wcout<<L"发送中\t";
}
wcout<<endl<<L"****发送完毕****"<<endl;
while(1)
{}
}
服务器先启动,等待接收文件,客户端后启动用来发送文件。双方用TCP连接好之后客户端先发送一个 LARGE_INTEGER 变量,变量中保存的是文件的大小。这个文件是光盘的压缩文件,右键属性显示1.48G。
发送完大小之后双方开始用 while 循环发送和接收,程序运行了大概20秒之后,双方都各自阻塞在自己的 recv 函数。下面客户端发送完文件大小之后,服务器就进入 while 循环开始接收数据,把收到的数据写入文件,在给客户 send 回去 WriteFile 了多少字节, 客户端收到服务器 WriteFile 多少字节之后调用文件的 SetFilePointerEx,以便下次从那继续发送下面是服务器端和客户端的代码和运行结果图
//服务器端(接收文件)#include<Windows.h>
#include<iostream>
using namespace std;const int iOneMBufferSize = 1024*1024;
char buffer[iOneMBufferSize];//一兆空间
void main()
{
setlocale(LC_ALL, "chs");
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,100);
int len = sizeof(addr);
SOCKET s2 = accept(s1,(SOCKADDR*) &addr,&len);
if( s2 != INVALID_SOCKET )
wcout<<L"***** 有客户端连入 *****"<<endl; LARGE_INTEGER i64FileSize, i64FileSizeCopy;
recv(s2,(char*)&i64FileSize, sizeof(i64FileSize), 0);
i64FileSizeCopy.QuadPart = i64FileSize.QuadPart;
wcout<<L"**** 文件大小是 "<< i64FileSize.QuadPart <<L"字节, 文件保存在C盘根目录下 ****"<<endl;
HANDLE hFile = CreateFile(L"C:\\接收文件.rar",
GENERIC_READ | GENERIC_WRITE,//读写权限
0,//不共享
0,//默认安全描述符
OPEN_ALWAYS,//存在就打开,不存在就创建
0,//Flags and Attributes
0);//hFileTemplate
if(hFile==INVALID_HANDLE_VALUE)
wcout<<L"**** 文件创建失败 ****"<<endl;
DWORD dwNumBytes;
while( i64FileSize.QuadPart>0)//这里的一堆wcout是为看出阻塞在哪
{
ZeroMemory(buffer, iOneMBufferSize);
wcout<<L"服务器准备接收文件"<<endl;
int size = recv(s2, buffer, iOneMBufferSize, 0);
wcout<<L"服务器收完文件"<<endl;
wcout<<L"服务器准写文件"<<endl;
WriteFile(hFile, buffer, size, &dwNumBytes, 0);
wcout<<L"服务器写完文件"<<endl; wcout<<L"服务器准备发送 dwNumBytes"<<endl;
send(s2, (char*)&dwNumBytes, sizeof(DWORD), 0);
wcout<<L"服务器发完 dwNumBytes"<<endl; i64FileSize.QuadPart -= dwNumBytes; // wcout<<L"接收中\t";
}
wcout<<endl<<L"****接收完毕****"<<endl;
while(1)
{}
}//客户端(发送文件)
#include<Windows.h>
#include<iostream>
using namespace std;const int iOneMBufferSize = 1024*1024;
char buffer[iOneMBufferSize];//一兆空间
void main()
{
setlocale(LC_ALL, "chs");
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);
char ip[100];
ZeroMemory(ip,100);
wcout<<L"输入对方IP: ";
cin>>ip;//这里输入 127.0.0.1
addr.sin_addr.S_un.S_addr = inet_addr(ip);
int e = connect(s1, (SOCKADDR*)&addr, sizeof(addr));
if(e==-1)
wcout<<L"connect 函数失败"<<endl; HANDLE hFile = CreateFile(L"C:\\Users\\ys\\Desktop\\Visual C++开发入行真功夫光盘二次.rar",
GENERIC_READ | GENERIC_WRITE,//读写权限
0,//不共享
0,//默认安全描述符
OPEN_ALWAYS ,//存在就打开,不存在就创建
0,//Flags and Attributes
0);//hFileTemplate
if(hFile==INVALID_HANDLE_VALUE)
wcout<<L"**** 文件读取失败 ****"<<endl; LARGE_INTEGER i64FileSize, i64FileSizeCopy;
GetFileSizeEx(hFile, &i64FileSize);
i64FileSizeCopy.QuadPart = i64FileSize.QuadPart;
wcout<<L"共需发送 " << i64FileSize.QuadPart <<L"字节" <<endl;
send(s1, (char*)&i64FileSize.QuadPart, sizeof(i64FileSize.QuadPart), 0);
DWORD dwNumBytes; while( i64FileSize.QuadPart >0 )//这里的一堆wcout是为看出阻塞在哪
{
ZeroMemory(buffer, iOneMBufferSize);
wcout<<L"客户端准备读文件"<<endl;
ReadFile(hFile, buffer, iOneMBufferSize, &dwNumBytes, 0);
wcout<<L"客户端读完文件"<<endl;
wcout<<L"客户端准备发送文件"<<endl;
send(s1, buffer, dwNumBytes, 0);
wcout<<L"客户端发完文件"<<endl; DWORD size;
wcout<<L"客户端准备接收服务器返回的 dwNumBytes"<<endl;
recv(s1, (char*)&size, sizeof(DWORD), 0);
wcout<<L"客户端收完服务器返回的 dwNumBytes"<<endl; LARGE_INTEGER move;
move.QuadPart = size;
wcout<<L"客户端准备设置文件指针"<<endl;
SetFilePointerEx(hFile, move, 0, FILE_CURRENT);
wcout<<L"客户端设完文件指针"<<endl;
i64FileSize.QuadPart -= size; wcout<<L"发送中\t";
}
wcout<<endl<<L"****发送完毕****"<<endl;
while(1)
{}
}
解决方案 »
- 关于MapViewOfFile函数的错误
- CrichEditCtrl中超链接文字的保存
- 急,那位兄弟快把vc6的头文件 XTREE 发过来
- 在ACCESS数据库中插数据问题
- 程序似乎是线程起多了,超过了内存限制。启动就死机。请问有这种限制吗?该怎么解决?急
- 去看看吧,很有趣!
- (100分):所有在读、读过、准备读 候sir《深入浅出MFC 2e》的程序员们进来坐坐,看看你们读书的效果如何
- Drag and Drop 问题,高手请进
- 对话框分割切换
- 如何动态得到某一结构体的各个成员类型????
- 赋值为'\0',为什么输出a
- 本人在学opengl,求高手帮忙怎样(if(dlg.DoModal()==IDOK) )得到图片的Filename和长宽,并代人下面的源码中(vc++)
假设,新来的数据已经到达网卡或内存,而我这里还在执行上一轮的 WriteFile,那完全可以在下一次循环到 recv 的时候在去读取数据,因为我这里都是同步的,而且没有采用任何五花八门的 flags 标志,因为没有使用 flags 标志所以网卡或内存中的数据会为我保留,只要过一会读取就好了。
况且我曾经试验过下面的做法:
接收端等待一个 cin 操作,而在 cin。之前对方早已经发送来了数据,我 cin 之后在去 recv 完全是正常的。所以时间不是问题。
send(s1, buffer, dwNumBytes, 0); 这里你需要判断发送和接收函数的返回结果, 有许多情况会导致返回SOCKET_ERROR, 而且不同情况处理也不同, 有些如WSAEWOULDBLOCK需要重发(收)数据详情请看MSDN关于这两个函数的介绍, 特别是re部分。
http://msdn.microsoft.com/en-us/library/ms740149(VS.85).aspx
http://download.csdn.net/detail/geoff08zhang/4571358
发送100字节->等结果接收50字节->发送结果这不就乱套了吗?你这种设计还有很多问题!比如你发送的结果,到接收方根本就不对,很有可能重复,比如像我上面说的例子。
请问你有好好看MSDN么? 不要想当然, MSDN上列出的那么多可能的错误你以为是白给的么? 只是你没怎么用没碰到而已