【转】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:本例源代码已保存至邮箱,即取即用