基于Socket的文件传输(使用CSocket类)

摘要:
OnBnClickedSend(){pThreadSend=AfxBeginThread(ThreadSend:

本软件使用MFC采用面向对象的方法实现了基于Socket的文件传输。这是原来研究生课程的结课作业,实现了Socket的发送和接收,以及读取ini配置文件等操作。使用了CSocket类

以下是当时结课作业 的正文:

 

一.软件特点如下:

 

1.      采用了多线程的方法,文件传输时使用AfxBeginThread()开启新线程

 

void CClientsockDlg::OnBnClickedSend()

{

   pThreadSend = AfxBeginThread(Thread_Send,this);/

 }

 

文件的发送和接收都开起了新线程

 

UINTThread_Send(LPVOID lpParam)

{

   代码略

}

 

2.      支持从配置文件configuration.ini中获取服务器参数

 

采用GetPrivateProfileString()GetPrivateProfileInt()分别获取位于ServerConfiguration.ini文件中的String类型的IPint类型的port

CString IP;

int port;

GetPrivateProfileString

(L"ServerConfiguration",L"IP",L"没有读取到数据!",IP.GetBuffer(10),10,L".\configuration.ini");

port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\configuration.ini");

                                                                                                            

 

3.      采用了面向对象的设计方式,功能之间按模块划分

MFC本身具有良好的面向对象的特性,本程序严格按照MFC框架结构编写代码,每个按钮对应一个功能函数,降低了代码之间的耦合性,有利于程序的扩展和复用。

 

void CServersockDlg::OnBnClickedChoose()

void CServersockDlg::OnBnClickedSend()

void CServersockDlg::OnBnClickedRecvdata()

void CServersockDlg::OnBnClickedAbout()

void CServersockDlg::OnBnClickedWriteini()

 

 

4.      采用了CSocket类,代码相对更简单

CSocket类是MFC框架对socket编程中的winsockAPI的封装,因此通过这个类管理收发数据更加便利。代码也跟那个既简单易懂。

        //创建

        if(!Clientsock.Socket())

        {

                  CString str;

                  str.Format(_T("Socket创建失败:%d"),GetLastError());

                  AfxMessageBox(str);

        }

        //连接

        if(!Clientsock.Connect(IP,port))

        {

                  CString str;

                  str.Format(_T("Socket连接失败:%d"),GetLastError());

                  AfxMessageBox(str);

        }

        else

        {

                  AfxMessageBox(_T("Socket连接成功"));

                代码略

        //发送

                  while(nSize<FindFileData.nFileSizeLow)

                  {

           szBuff = new char[1024];

                           memset(szBuff,0x00,1024);

                           nSend =file.Read(szBuff,1024);

                           Clientsock.Send(szBuff,nSend);//发送数据

                           nSize += nSend;

                  }

                  file.Close();

                  delete szBuff;

                  Clientsock.Close();

                  (dlg->GetDlgItem(IDC_SEND))->EnableWindow(TRUE);

                  AfxMessageBox(_T("文件发送成功"));

                  dlg->SetDlgItemTextW(IDC_FILEPATHNAME,_T(""));

        }

        return 0;

 

 

5.      支持数据在服务器与客户端之间双向传输

 

本程序不但可以从客户端往服务器端传文件,而且可以从服务器端往客户端传文件。

但是互传文件的方式并不是完全相同的。

服务器端不管是接收文件还是发送文件始终是对绑定的端口进行监听。

   //绑定

   if(!Serversock.Bind(port))

   {

       CString str;

      str.Format(_T("Socket绑定失败: %d"),GetLastError());

       AfxMessageBox(str);

   }

   //监听

   if(!Serversock.Listen(10))

   {

       CString str;

       str.Format(_T("Socket监听失败:%d"),GetLastError());

       AfxMessageBox(str);

   }

 

 

客户端不管是接收文件还是发送文件始终是进行连接。

   if(!Clientsock.Connect(IP,port))

   {

       CString str;

       str.Format(_T("Socket连接失ì:%d"),GetLastError());

       AfxMessageBox(str);

   }

   else

   {

       

 

6.      完全图形化操作界面

 

 

二.软件使用说明

 

客户端主界面如图所示:

 

u 单击“选择文件”弹出文件对话框,选择一个要发送的文件,同时保存文件的路径。

u 单击“发送”则会读取ServerConfiguration.ini文件中的配置信息(IPport),并根据此信息建立Socket连接,发送文件。注意:服务器端应该先单击了“接受客户端数据”,否则发送失败。

u 单击“接收”也会读取ServerConfiguration.ini文件中的配置信息(IPport),并根据此信息建立Socket连接,接收文件。注意:服务器端应该先选择了向客户端发送的文件,并单击了“发送”,否则接受失败。

u 单击“读取配置文件”,会从ServerConfiguration.ini文件中读取配置信息,并以可编辑的文本形式显示出来,修改完后,单击“写入配置文件”,会将修改后的信息保存到配置文件中。

u 单击“关于”可以了解到软件相关信息。

u 代码注释里有更详细的说明

基于Socket的文件传输(使用CSocket类)第1张

服务器端主界面如图所示

 

u 单击“接受客户端数据”,开始监听客户端的链接。

u  单击“选择文件”弹出文件对话框,选择一个要发送的文件,同时保存文件的路径。

u  单击“发送”则会读取ServerConfiguration.ini文件中的配置信息(port),并监听对应端口,准备发送文件。注意:客户端选择“接收”以后才能发送成功。

u  单击“读取配置文件”,会从ServerConfiguration.ini文件中读取配置信息,并以可编辑的文本形式显示出来,修改完后,单击“写入配置文件”,会将修改后的信息保存到配置文件中。但是服务器的IP是不可以修改的,它是在程序开始运行时从服务器所在机器的网卡上获取的。

u  单击“关于”可以了解到软件相关信息。

u  代码注释里有更详细的说明

 基于Socket的文件传输(使用CSocket类)第2张

 

 

 

代码下载地址:http://download.csdn.net/detail/leixiaohua1020/6320417

 

在此附上客户端使用CSocket发起连接的代码

//----------------------------发送文件的线程------------------------------
UINT Thread_Send(LPVOID lpParam)
{
	CClientsockDlg *dlg=(CClientsockDlg *)lpParam;
    (dlg->GetDlgItem(IDC_SEND))->EnableWindow(FALSE);

	CSocket Clientsock; //definition socket.
	if(!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
	}

	CString IP;
	int port;
	GetPrivateProfileString(L"ServerConfiguration",L"IP",L"没有读取到数据!",IP.GetBuffer(100),100,L".\configuration.ini");
	port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\configuration.ini");
	//创建
	if(!Clientsock.Socket())
	{
		CString str;
		str.Format(_T("Socket创建失败: %d"),GetLastError());
		AfxMessageBox(str);
	}
	//连接
//	if(!Clientsock.Connect(_T("127.0.0.1"),8088))
	if(!Clientsock.Connect(IP,port))
	{
		CString str;
		str.Format(_T("Socket连接失败: %d"),GetLastError());
		AfxMessageBox(str);
	}
	else
	{
		AfxMessageBox(_T("Socket连接成功"));
		WIN32_FIND_DATA FindFileData;
		CString strPathName; //定义用来保存发送文件路径的CString对象
		dlg->GetDlgItemTextW(IDC_FILEPATHNAME,strPathName);
		FindClose(FindFirstFile(strPathName,&FindFileData));
		Clientsock.Send(&FindFileData,sizeof(WIN32_FIND_DATA));
        
		CFile file;
		if(!file.Open(strPathName,CFile::modeRead|CFile::typeBinary))
		{
			AfxMessageBox(_T("文件不存在"));
			return 1;
		}

		UINT nSize = 0;
		UINT nSend = 0;

		char *szBuff=NULL;
	//发送
		while(nSize<FindFileData.nFileSizeLow)
		{
            szBuff = new char[1024];
			memset(szBuff,0x00,1024);
			nSend = file.Read(szBuff,1024);
			Clientsock.Send(szBuff,nSend);//发送数据
			nSize += nSend;
		}
		file.Close();
		delete szBuff;
		Clientsock.Close();
		(dlg->GetDlgItem(IDC_SEND))->EnableWindow(TRUE);
		AfxMessageBox(_T("文件发送成功"));
		dlg->SetDlgItemTextW(IDC_FILEPATHNAME,_T(""));
	}
	return 0;
}


 

以及服务器端使用CSocket监听的代码:

//----------------------------监听文件的线程------------------------------
UINT Thread_Func(LPVOID lpParam)  //接收文件的线程函数
{
	CServersockDlg *dlg = (CServersockDlg *)lpParam; //获取对话框指针
    (dlg->GetDlgItem(IDC_RECVDATA))->EnableWindow(FALSE);

	if(!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
	}

	CString IP;
	int port;
	GetPrivateProfileString(L"ServerConfiguration",L"IP",L"没有读取到数据!",IP.GetBuffer(100),100,L".\configuration.ini");
	port=GetPrivateProfileInt(L"ServerConfiguration",L"port",0,L".\configuration.ini");
    
	char errBuf[100]={0};// 临时缓存
    
	SYSTEMTIME t; //系统时间结构 

	CFile logErrorfile;
	if(!logErrorfile.Open(_T("logErrorfile.txt"),CFile::modeCreate|CFile::modeReadWrite))
	{
		return 1;
	}

	CSocket Serversock;
    CSocket Clientsock;
	//创建
	if(!Serversock.Socket())
	{
		CString str;
		str.Format(_T("Socket创建失败: %d"),GetLastError());
		AfxMessageBox(str);
	}

	BOOL bOptVal = TRUE;
	int bOptLen = sizeof(BOOL);
	Serversock.SetSockOpt(SO_REUSEADDR,(void *)&bOptVal,bOptLen,SOL_SOCKET);

	//绑定
	if(!Serversock.Bind(port))
	{
		CString str;
		str.Format(_T("Socket绑定失败: %d"),GetLastError());
		AfxMessageBox(str);
	}
    //监听 
	if(!Serversock.Listen(10))
	{
		CString str;
		str.Format(_T("Socket监听失败: %d"),GetLastError());
		AfxMessageBox(str);
	}

	GetLocalTime(&t);
	sprintf_s(errBuf,"服务器已经启动...正在等待接收文件...
时间:%d年%d月%d日 %2d:%2d:%2d 
",t.wYear,t.wMonth,t.wDay,
		t.wHour,t.wMinute,t.wSecond);
	int len = strlen(errBuf);
	logErrorfile.Write(errBuf,len);
	AfxMessageBox(_T("启动成功等待接收文件"));
	while(1)
	{
		//AfxMessageBox(_T("服务器启动成功..."));
		if(!Serversock.Accept(Clientsock)) //等待接收 
		{
			continue;
		}
		else
		{
			WIN32_FIND_DATA FileInfo;
			Clientsock.Receive(&FileInfo,sizeof(WIN32_FIND_DATA));

			CFile file;
			file.Open(FileInfo.cFileName,CFile::modeCreate|CFile::modeWrite);
			//AfxMessageBox(FileInfo.cFileName);
			int length = sizeof(FileInfo.cFileName);
			logErrorfile.Write(FileInfo.cFileName,length);
			//Receive文件的数据

			UINT nSize = 0;
			UINT nData = 0;

			char *szBuff=NULL;

			while(nSize<FileInfo.nFileSizeLow)
			{
				szBuff = new char[1024];
				memset(szBuff,0x00,1024);
				nData=Clientsock.Receive(szBuff,1024);
			    file.Write(szBuff,nData);
				nSize+=nData;
			}

			delete szBuff;
			Serversock.Close();
			Clientsock.Close();
			file.Close();
			(dlg->GetDlgItem(IDC_RECVDATA))->EnableWindow(TRUE);
			sprintf_s(errBuf,"文件接收成功...
时间:%d年%d月%d日 %2d:%2d:%2d 
",t.wYear,t.wMonth,t.wDay,
		t.wHour,t.wMinute,t.wSecond);
			int len = strlen(errBuf);
			logErrorfile.Write(errBuf,len);
			//AfxMessageBox(_T("文件接收成功..."));
		    break;
		}
	}
	return 0;
}


 

免责声明:文章转载自《基于Socket的文件传输(使用CSocket类)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL- exists的用法介绍(返回值True或False)-not exists反过来查询的应用vsftpd安装及虚拟用户配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python setup.py 构建

摘要:这篇文章描述了自己动手把需要的代码封装成python模块的方法。完成后,我们可以直接使用pip install xxx下载自己的模块并使用内置的函数。 介绍python作为一门鼎鼎大名的语言,最有优势的地方就是它拥有无数第三方的模块可以直接拿来使用。以numpy(一个用于实现科学计算的模块)为例,常见的用法一般是这样,相信写过python的肯定是见得...

OD与调试符号

在使用WinDBG时,要加载调试符号则是使用的编译器生成的标准PDB调试库。 而在OD中,有两类调试信息来源: 1.PDB文件 2.LIB文件 其中,LIB文件在查找导入符号时,能够发挥重要的作用。 下文将解释OD和VS2008使用LIB库的一些条件: 1.简介 例如众所周知的MFC库大量使用了DLL导出序号,因此在OD中查看这些导入信息时,都只能看到序号...

Python面向对象(类和对象)

自从存在以来,Python一直是面向对象的语言。 因此,创建和使用类和对象是非常容易的。 本章将学习如何使用Python面向对象编程。如果您以前没有面向对象(OO)编程的经验,可能需要查阅介绍面向对象(OO)编程课程或至少学习一些有关教程,以便掌握基本概念。下面是面向对象编程(OOP)的一个小介绍,以帮助您快速入门学习 -OOP术语概述类 - 用于定义表示用...

局域网中Ubuntu和Windows进行文件夹共享

http://www.linuxeden.com/html/netadmin/20071106/37043.html 首先安装Samba:   sudo apt-get install samba   一、在ubuntu下查看局域网中windows系统共享的文件夹:   在“位置”--“网络”--“Windows 网络”中就能看到其它的windows主机和...

PHP5环境非安装配置 以及 EClipse单步调试配置 的方法 100%成功

在Windows平台配置PHP环境 注意:要按此配置搭建好环境,必须使用我的PHP.INI文件(已经配置好的),下载地址:/Files/lixyvip/php_ini.rar 假设PHP的全部文件放到D盘下的PHP文件夹 目录结构如下:d:\php\d:\php\ext\ php.ini文件在:d:\php\php.ini 1、我的电脑->属性-&g...

linux ls命令按时间显示文件

  本文介绍下,使用ls命令显示文件,并按时间排序的方法,供大家学习参考。 在linux系统中,使用ls命令按时间排序文件,其实很简单,如下: #ls -tr 即可按时间排序当前目录下的文件。 附,ls命令的参数中文详解: -a 列出目录下的所有文件,包括以 . 开头的隐含文件。 -b 把文件名中不可输出的字符用反斜杠加字符编号(就象在C语言里一样)的形式...