文档章节

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

abcijkxyz
 abcijkxyz
发布于 2016/08/06 12:26
字数 1794
阅读 7
收藏 0

本软件使用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 代码注释里有更详细的说明

服务器端主界面如图所示

 

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

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

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

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

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

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

 

 

 

 

 

代码下载地址: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,"服务器已经启动...正在等待接收文件...\r\n时间:%d年%d月%d日 %2d:%2d:%2d \r\n",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,"文件接收成功...\r\n时间:%d年%d月%d日 %2d:%2d:%2d \r\n",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;
}


 

 

本文转载自:http://blog.csdn.net/leixiaohua1020/article/details/12025731

共有 人打赏支持
abcijkxyz
粉丝 63
博文 6196
码字总数 1876
作品 0
深圳
项目经理
私信 提问

暂无文章

Python中判断字符串是否包含中文

Python import reRE = re.compile(u'[\u4e00-\u9fa5]', re.UNICODE)match = re.search(RE, str)if match is None:# 没有包含中文字符 参考 Python regular expressions return true/f......

亚林瓜子
4分钟前
0
0
《CNCF × Alibaba 云原生技术公开课》正式首播

《CNCF × Alibaba 云原生技术公开课》立即观看:点击立即观看 云原生最初来描述云上应用的典型架构与特性,随着容器、Kubernetes、Serverless、FaaS技术的演进,CNCF(云原生计算基金会)把...

mcy0425
4分钟前
0
0
网站漏洞如何修复网站程序问题

jeecms 最近被爆出高危网站漏洞,可以导致网站被上传webshell木马文件,受影响的版本是jeecms V6.0版本到jeecmsV7.0版本。该网站系统采用的是JAVA语言开发,数据库使用的是oracle,mysql,sql数...

网站安全
8分钟前
0
0
git 中“warning: CRLF will be replaced by LF in”解决方案

https://stackoverflow.com/questions/5834014/lf-will-be-replaced-by-crlf-in-git-what-is-that-and-is-it-important...

qwfys
12分钟前
0
0
Spring Boot配置ssl证书启用HTTPS协议

一 、点睛 SSL是为网络通信提供安全及数据完整性的一种安全协议,SSL在网络传输层对网络连接进行加密。SSL协议位于TCP/IP协议和各种应用层协议之间,为数据通信提供安全支持。 SSL协议分为两...

故久呵呵
14分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部