【转】DOS下文件传输---<<初识TCP网络编程>>改版

更新版说明:
1.在以前基础上,添加了错误提示,方便查询---使用SOCKET_ERROR检测
2.在以前基础上,添加了文件传输模块--------使用CreateFile中ReadFile与WriteFile
3.修改完成后,使用MessageBox弹出窗口提示--确保用户的每一步操作都正常完成,且配备提示
4.修改变量名,更标准化--------------------如s1改成sServer(小s代表socket,大S表示服务端)等
5.增强了注释部分,使程序通俗易懂
6.完整的封装性---------------------------使用#pragma comment(lib,"Ws2_32.lib"),复制过去不用在工程里设置链接库
7.防止内存泄漏---------------------------只要发生错误,或完成任务,都必须马上清理内存,释放资源


------------代码部分分2部分:1.服务端代码 2.客户端代码----------------------

-----------------------------------1.服务端代码--------------------------------------

#include<Winsock2.h>//WSAStartup等需要包含的头文件
#include <windows.h>//CreateFile等需要包含的头文件---注意第1行与第2行包含的顺序---详见备注1
#include <stdio.h>
#include<iostream>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")

void main()
{
/////////////////////////////第1步:初始化Windsock部分/////////////////////
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup( wVersionRequested, &wsaData );//注:配套的析构函数WSACleanup
if ( err != 0 ) {
   /* Tell the user that we could not find a usable */
   /* WinSock DLL.                                  */
   return;
}

/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater    */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we      */
/* requested.                                        */

if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
   /* Tell the user that we could not find a usable */
   /* WinSock DLL.                                  */
   WSACleanup( );                                   //WSAStartup配套的析构函数WSACleanup
   return;
}
/* The WinSock DLL is acceptable. Proceed. */

///////////////////////第2步:创建套接字socket部分/////////////////////////////
SOCKET sServer=socket(AF_INET,SOCK_STREAM,0); //配套的析构函数closesocket(socket);
if(sServer==INVALID_SOCKET){cout<<"创建套接字错误!"<<endl;closesocket(sServer);WSACleanup();}//或SOCKET_ERROR

///////////////////////第3步:绑定套接字bind部分///////////////////////////////
SOCKADDR_IN sbind;
sbind.sin_family=AF_INET;
sbind.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
sbind.sin_port=htons(6000);
if(SOCKET_ERROR==bind(sServer,(SOCKADDR*)&sbind,sizeof(SOCKADDR)))
   {cout<<"绑定套接字错误!"<<endl;closesocket(sServer);WSACleanup();}

///////////////////////第4步:监听套接字部分////////////////////////////////////  
if(SOCKET_ERROR==listen(sServer,10)){cout<<"监听套接字错误!"<<endl;closesocket(sServer);WSACleanup();}

///////////////////////第5步:接收客户端部分////////////////////////////////////
SOCKET sAccept=SOCKET_ERROR;SOCKADDR_IN addr_accept;int len=sizeof(SOCKADDR);cout<<"接收客户端套接字开始:";
while(1)
{
   while(sAccept==SOCKET_ERROR)
   {
    sAccept=accept(sServer,(SOCKADDR*)&addr_accept,&len);
   }
   break;
}
sServer=sAccept;cout<<"接收客户端套接字,成功!"<<endl;

///////////////////////第6步:发送文件部分//////////////////////////////////////
HANDLE hFile=CreateFile("C:\\1.jpg",GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
char sendbuf[1024];DWORD dwRead;BOOL nReadFile;
while(1)
{
///////////ReadFile部分/////////////////////
   nReadFile=ReadFile(hFile,sendbuf,1024,&dwRead,0);
   if(nReadFile==0)
    {cout<<"ReadFile读取文件时错误!"<<endl;CloseHandle(hFile);closesocket(sServer);WSACleanup();break;}
   else if(dwRead==0)
   {
    MessageBox(0,"成功发送文件到客户端!等待客户接受完后退出","MB_OK",0);
    CloseHandle(hFile);//千万别加closesocket(sServer);WSACleanup();因为send还没有用呢
    break;
   }
///////////send部分/////////////////////////
   if(SOCKET_ERROR==send(sServer,sendbuf,1024,0))
    {cout<<"ReadFile读取文件时错误!"<<endl;CloseHandle(hFile);closesocket(sServer);WSACleanup();}  
}
}

-----------------------------------2.客户端代码--------------------------------------

#include<Winsock2.h>
#include <windows.h>
#include <stdio.h>
#include<iostream>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")

void main()
{
/////////////////////////////第1步:初始化Windsock部分/////////////////////
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
   /* Tell the user that we could not find a usable */
   /* WinSock DLL.                                  */
   return;
}

/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater    */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we      */
/* requested.                                        */

if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
   /* Tell the user that we could not find a usable */
   /* WinSock DLL.                                  */
   WSACleanup( );
   return;
}
/* The WinSock DLL is acceptable. Proceed. */

///////////////////////第2步:创建套接字socket部分/////////////////////////////
SOCKET sClient=socket(AF_INET,SOCK_STREAM,0); //配套的析构函数closesocket(socket);
if(sClient==INVALID_SOCKET){cout<<"创建套接字错误!"<<endl;closesocket(sClient);WSACleanup();}//或SOCKET_ERROR

///////////////////////第3步:连接服务端部分///////////////////////////////////
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(6000);
if(SOCKET_ERROR==connect(sClient,(SOCKADDR*)&addr_conect,sizeof(SOCKADDR)))
   {cout<<"连接服务端错误!"<<endl;closesocket(sClient);WSACleanup();}

//////////////////////第4步:接收文件部分//////////////////////////////////////
HANDLE hFile=CreateFile("D:\\1.jpg",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
char recvbuf[1024];DWORD dwRecv;BOOL bWriteFile;
while(1)
{
////////////////////recv部分//////////////////
   if(SOCKET_ERROR==recv(sClient,recvbuf,1024,0))   
   {cout<<"recv接受完成!"<<endl;CloseHandle(hFile);closesocket(sClient);WSACleanup();break;}  
   //注:此SOCKET_ERROR返回2个信息:1.创建未成功时,返回的错误,2.消息发完后,返回的错误值...切记注意判断
///////////////////WriteFile部分//////////////
   bWriteFile=WriteFile(hFile,recvbuf,1024,&dwRecv,0);
   if(bWriteFile==0)
   {cout<<"WriteFile写入文件错误!"<<endl;CloseHandle(hFile);closesocket(sClient);WSACleanup();break;}
}
MessageBox(0,"写入文件成功!现在退出","MB_OK",0);
}
备注1:注意#include<Winsock2.h>(在前)与#include <windows.h>(在后)包含顺序,因为window.h默认(未申明)包含是1版,所以引起冲突
备注2:接受后的文件,比原文件多了1字节.比如原有是109KB,发送过来后是110KB

客户端备注1:
之前服务端,有写过,但是这是客户端,无须写.如果是双向的,也就是即当服务也当客户端,那就可能要写了
if(dwRecv==0)
{
MessageBox(0,"写入文件成功!现在退出","MB_OK",0);
CloseHandle(hFile);closesocket(sClient);WSACleanup();break;
}
客户端备注2:
为什么接受过来的东西,有那个文件,但是里面却什么也没有且文件大小0?
注意CreatFile中的CREATE_ALWAYS,MSDN中介绍如果没有文件,新建一个.如果有文件,则清除现有文件信息,并将值赋给它

---------

附注1:本例源代码已保存至邮箱,即取即用

posted @ 2012-05-16 22:20  完美视界  阅读(198)  评论(0编辑  收藏  举报