【转】网络文件传输2之C语言版的FILE
用这个,主要是为跨平台考虑.ACE现在有封装C语言的FILE功能,有些函数大同小异
以下是代码:
-----------------------服务端-----------------------
#include "stdafx.h"#include<Winsock2.h>
#include <windows.h>
#include <stdio.h>
#include<iostream>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
::WSAStartup(0x0002,&wsaData);
SOCKET sServer=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN sbind;
sbind.sin_family=AF_INET;
sbind.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
sbind.sin_port=htons(12345);
bind(sServer,(SOCKADDR*)&sbind,sizeof(SOCKADDR));
listen(sServer,10);
SOCKADDR_IN addr_accept;
int len=sizeof(SOCKADDR);
printf("接收客户端套接字开始:\n");
SOCKET Server;
Server=accept(sServer,(SOCKADDR*)&addr_accept,&len);
printf("发送文件!\n====================================\n");
////////////////////////发送文件部分:独立模块
FILE *fp;
if( (fp = fopen( "C:\\5.JPG", "rb" )) == NULL )
{printf( "The file 'data' was not opened\n" );return 0;}
printf( "The file 'data' was opened\n" );
fseek(fp,0,SEEK_END);//因为ftell定义Gets the current position of a file pointer.
long nlenTotal=ftell(fp); //所以将指针移到文件最后.
char sendbuf[1024]={0};
fseek(fp,0,SEEK_SET);
int nlenAlready = 0;
while(1)
{
if(nlenTotal==0)
{
printf("文件已读完,能够退出了\n");
break;
}
else
{
fseek(fp,nlenAlready,SEEK_SET);//必须用.默认是读多少自动移多少,缺点是出错了也是继续向后移,这里就必须人工干预了
int nfread=fread(&sendbuf,1,1024,fp);
if(SOCKET_ERROR==send(Server,(char*)&sendbuf,nfread,0))//参数3,是指定发送的大小,在最后一次肯定小于1024字节,比如500字节,这里只从缓冲区读500字节发出去.客户端收到实际是500字节,不会造成客户端问题
{
printf("send错误:nSend==-1\n");//这个地方出错了,不要closesocket之类或者break/return 0之类退出,重发即可
}
else
{
nlenTotal=nlenTotal-nfread;
nlenAlready += nfread;
}
}
}
Sleep(5000);//视文件长度停止多长时间,因为上面的发文件是一发完就退出程序,此时若接受方没收完,会报10054的错误
if( fclose( fp ) )
printf( "The file 'data' was not closed\n" );
printf("已发包!\n====================================\n");
return 0;
}
-----------------------客户端-----------------------
#include "stdafx.h"
#include<Winsock2.h>
#include <windows.h>
#include <stdio.h>
#include<iostream>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
::WSAStartup(0x0002,&wsaData);
SOCKET sClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addr_conect;
addr_conect.sin_family=AF_INET;
addr_conect.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addr_conect.sin_port=htons(12345);
if(SOCKET_ERROR==connect(sClient,(SOCKADDR*)&addr_conect,sizeof(SOCKADDR)))
{cout<<"连接服务端错误!"<<endl;closesocket(sClient);WSACleanup();return 0;}
printf("==============================\n开始接收文件\n");
////////////////////////接受文件部分:独立模块
char recvbuf[1024]={0};
int nfwrite=0;
DWORD nRecv=0;
int nlen=62732;//文件长度
int nlenRecv=0;
FILE *fp;
if( (fp = fopen( "D:\\5.JPG", "wb" )) == NULL )
{printf( "The file 'data' was not opened\n" );return 0;}
printf( "The file 'data' was opened\n" );
do
{
nRecv=recv(sClient,recvbuf,sizeof(recvbuf),0);
printf("recv长度=%d\n",nRecv);
if(SOCKET_ERROR==nRecv)
{
printf("recv错误:SOCKET_ERROR==nRecv,错误码=[%d]\n",WSAGetLastError());
//注意用WSAGetLastError()获取错误码,注意10054是超时(或者理解成Connection reset by peer)
break;
}
else if(nRecv==0)
{
printf("连接断开\n");
break;
}
else
{
nlenRecv=nlenRecv+nRecv;
nfwrite=fwrite(&recvbuf,1,nRecv,fp);
if(nfwrite==0)
{printf("file write error!\n");return 0;}
}
}while(nlenRecv!=nlen);
printf("文件传输完成,接受的文件总长=%d,nlen=%d\n",nlenRecv,nlen);
fclose(fp);
printf("发送完文件\n==============================\n");
closesocket(sClient);
WSACleanup();
return 0;
}
//备注1:文件长度
//int nlen=62732;//文件长度.按道理是发送方告诉接受方的,此处为不影响主题,所以直接把长度写进接受方,不过用的时候要注意一定要告诉对方你的文件长度
//备注2:文件路径
//发送方C:\\5.JPG,接受方D:\\5.JPG//
//备注3:图片在文章中大小是62732
附注1:服务端用的是FILE,客户端用的是CFile.更新中..
浙公网安备 33010602011771号