一个基于socket的资源共享平台的实现(三)

需要共享资源,则需要探测本地资源分布情况。

此处我们用的算法比较2……不过还是说说吧。

 

下面使用MFC的CFileFind实现一个本地文件递归收集器,以jason格式存储文件路径和文件大小:

 

#ifndef COLLECTER_H_
#define COLLECTER_H_


#include<iostream>
#include<vector>

#include "StdioFileEx/StdioFileEx.h"

#define TargetFile "result.txt"
#define CfgFileName "path.txt"

using namespace std;

struct FileStruct
{
	CString path;
	__int64 size;
};

vector<FileStruct> files;

void findfile(CString dir)
{
	CFileFind finder;

	BOOL bWorking = finder.FindFile(dir + _T("\\*.*"));

	while (bWorking)
	{
		bWorking = finder.FindNextFile();

		//列举文件
		if( finder.IsDots() == false && finder.IsDirectory() == false )
		{
			FileStruct file;
			CString tmp = dir + _T("\\") + CString( finder.GetFileName() );

			//只传送文件名
			//CString tmp = CString( finder.GetFileName() );

			file.path = tmp;

			__int64 iFileLenInByte = (__int64)finder.GetLength();

			__int64 size = iFileLenInByte;

			file.size = size;
			files.push_back( file );
		}

		//递归访问子目录
		if( finder.IsDirectory() &&
			finder.IsDots() == false )
			findfile( dir + _T("\\") + CString( finder.GetFileName() ) );
	}
}

/*

[{"f_name":"文件名","f_hash":"文件哈希,32字符","f_length":null/片长,数字不要加引号,"f_type":null/"文件类型就后缀吧先","f_time":null/"年代字符串 加双引号","f_intro":"简介,类似年代"},{}...{}]

*/

void WriteResult()
{
	CStdioFileEx fp;
	fp.Open(_T(TargetFile),CFile::modeWrite|CFile::modeCreate); 

	fp.WriteString( _T("["));
	for( vector<FileStruct>::iterator iter = files.begin(); iter != files.end(); ++iter)
	{
		if( iter !=  files.begin() )
			fp.WriteString(_T(","));
		CString MyFileSize;
		MyFileSize.Format(_T("%ld"),iter->size);

		fp.WriteString(_T("{\"fname\":\""));
		fp.WriteString( iter->path );
		fp.WriteString(_T("\","));
		fp.WriteString(_T("\"fsize\":\""));
		fp.WriteString( MyFileSize );
		fp.WriteString(_T("\"}"));
		//fp.WriteString( iter->size );
	}
	fp.WriteString( _T("]"));
	fp.Close(); 
}

void ReadCfg(CString& path)
{
	CStdioFileEx fp;
	fp.Open(_T(CfgFileName),CFile::modeRead);
	fp.ReadString( path );
	fp.Close(); 
}

void StartCollect()
{
	CString SearchPath;
	ReadCfg( SearchPath );
	cout<<"searching please wait."<<endl;;
	findfile( SearchPath );
	WriteResult();
	cout<<"finish"<<endl;
	system("pause");
}


#endif

 

 

然后定期收集,对收集结果MD5,若发生变化,则上传服务器。

服务器端使用一个数据结构维护所有资源站资源,对于用户的搜索,我们此处使用最简单的比较方法,看是否包含子串,此处就不详加介绍了。

 

服务器对所有的客户端进行集中管理,需要维护一张在线用户列表。

关于服务器如何探测资源站是否在线,TCP主动的的连接与断开可以检测到,但是若是被动的断线等,是无法正确响应的。所以此处我们还是使用心跳包模型——客户端每隔一段时间就向服务器发送心跳包,证明自己还“活着”,服务器若长时间没有收到某个客户端的心跳,则认为它“死掉”了,就从在线列表里将其KICK。

 

服务器端我们是使用的CONSOLE管理,实际就是单开一个control线程,可以由管理员输入命令进行管理。如查询在线列表、查询资源、踢出用户、广播消息等,这里也不加详细介绍了。

 

服务器需要维护LOG文件,如下所示:

 

【2010-01-25 9:0:24】开启服务器
【2010-01-25 9:0:31】127.0.0.1登入服务器
【2010-01-25 9:0:31】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:1:32】127.0.0.1长时间未响应,从服务器移除
【2010-01-25 9:3:20】开启服务器
【2010-01-25 9:3:23】0.0.0.0申请搜索,关键字 =
【2010-01-25 9:3:30】开启服务器
【2010-01-25 9:3:34】127.0.0.1登入服务器
【2010-01-25 9:3:34】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:3:37】0.0.0.0申请搜索,关键字 =
【2010-01-25 9:3:42】0.0.0.0申请搜索,关键字 = 1
【2010-01-25 9:4:14】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:5:19】127.0.0.1广播消息:sss
【2010-01-25 9:5:21】127.0.0.1广播消息:ahaha
【2010-01-25 9:5:23】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:6:0】127.0.0.1长时间未响应,从服务器移除
【2010-01-25 9:7:9】127.0.0.1登入服务器
【2010-01-25 9:7:9】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:7:46】127.0.0.1长时间未响应,从服务器移除
【2010-01-25 9:9:25】127.0.0.1登入服务器
【2010-01-25 9:9:26】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:14:39】127.0.0.1登入服务器
【2010-01-25 9:15:15】127.0.0.1长时间未响应,从服务器移除
【2010-01-25 9:17:33】127.0.0.1登入服务器
【2010-01-25 9:17:33】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:17:42】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:18:41】127.0.0.1长时间未响应,从服务器移除
【2010-01-25 9:19:7】127.0.0.1登入服务器
【2010-01-25 9:19:8】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:19:45】127.0.0.1长时间未响应,从服务器移除
【2010-01-25 9:20:6】127.0.0.1登入服务器
【2010-01-25 9:20:7】127.0.0.1申请搜索,关键字 =
【2010-01-25 9:21:56】127.0.0.1长时间未响应,从服务器移除
【2010-03-10 14:24:49】开启服务器
【2010-03-10 14:25:50】59.175.191.118登入服务器
【2010-03-10 14:28:18】127.0.0.1登入服务器
【2010-03-10 14:28:18】127.0.0.1申请搜索,关键字 =
【2010-03-10 14:29:32】系统广播消息:test
【2010-03-10 14:29:32】系统广播消息:test
【2010-03-10 14:30:44】127.0.0.1长时间未响应,从服务器移除
【2010-03-10 14:30:53】123.118.15.209登入服务器
【2010-03-10 14:30:54】123.118.15.209申请搜索,关键字 =

 

这里是我的服务器日志类。

 

需要注意的是由于多线程写日志,需要线程互斥访问log文件,注意 is_busy 变量。

#ifndef NETSHARE_LOG_H_
#define NETSHARE_LOG_H_

#include <string>
#include <vector>
#include <fstream>
#include <ctime> 

using namespace std;

//服务器日志管理类
class NS_Log
{
public:
	NS_Log( string filename )
		: logfile( filename.c_str(), ios::app )
		, is_busy( false )
	{}

	~NS_Log()
	{
		logfile.close();
	}

	void Write( string dat )
	{
		while( is_busy ) //互斥
		{
			Sleep( 20 );
		}
		is_busy = true;
		string now_time = GetNowTime();
		logfile<<"【"<<now_time<<"】"<<dat<<endl;
		is_busy = false;
	}
	
private:

	//获取当前时间
	string GetNowTime()
	{
		char pTime[1000];
		int year=0,mon=0,day=0,hour=0,min=0,sec=0;
		time_t now_time; 
		now_time = time(NULL); 
		struct tm *m_tm; 
		m_tm = gmtime(&(time_t)now_time);
		year = m_tm->tm_year+1900;
		mon = m_tm->tm_mon+1;
		day = m_tm->tm_mday;
		hour = m_tm->tm_hour;
		min = m_tm->tm_min;
		sec = m_tm->tm_sec; 
		sprintf(pTime, "%04d-%02d-%02d %d:%d:%d", year, mon, day, hour, min, sec);
		return string( pTime );
	}

	fstream logfile;
	bool is_busy;
};


#endif

 

 

未完待续……

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值