TeamTalk源码分析之msfs

TeamTalk全套源码 TeamTalk是一套开源的企业办公即时通讯软件,作为整套系统的组成部分之一,TTServer为TeamTalk 客户端提供用户登录,消息转发及存储等基础服务。 TTServer主要包含了以下几种服务器: LoginServer (C++): 登录服务器,分配一个负载小的MsgServer给客户端使用 MsgServer (C++): 消息服务器,提供客户端大部分信令处理功能,包括私人聊天、群组聊天等 RouteServer (C++): 路由服务器,为登录在不同MsgServer的用户提供消息转发功能 FileServer (C++): 文件服务器,提供客户端之间的文件传输服务,支持在线以及离线文件传输 MsfsServer (C++): 图片存储服务器,提供头像,图片传输中的图片存储服务 DBProxy (JAVA): 数据库代理服务器,提供mysql以及redis的访问服务,屏蔽其他服务器与mysql与redis的直接交互 附件中的代码包括了: 1、以上所有服务端的代码 2、PHP的后台管理系统 3、客户端代码:iOS版、Mac版、android版、Windows版 立即下载

客户端以http的方式来上传和下载聊天图片。

可能很多同学对http协议不是很熟悉,或者说一知半解。这里大致介绍一下http协议,http协议其实也是一种应用层协议,建立在tcp/ip层之上,其由包头和包体两部分组成(不一定要有包体),看个例子:

比如当我们用浏览器请求一个网址http://www.hootina.org/index.PHP,实际是浏览器给特定的服务器发送如下数据包,包头部分如下:

GET /index.php HTTP/1.1\r\n
Host: www.hootina.org\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n
User-Agent: Mozilla/5.0\r\n
\r\n

这个包没有包体。

从上面我们可以看出一个http协议大致格式可以描述如下:

[plain] view plain copy

  1. GET或Post请求方法  请求的资源路径 http协议版本号\r\n  
  2. 字段名1:值1\r\n  
  3. 字段名2:值2\r\n  
  4. 字段名3:值3\r\n  
  5. 字段名4:值4\r\n  
  6. 字段名5:值5\r\n  
  7. 字段名6:值6\r\n  
  8. \r\n  

 

 

也就是是http协议的头部是一行一行的,每一行以\r\n表示该行结束,最后多出一个空行以\r\n结束表示头部的结束。接下来就是包体的大小了(如果有的话,上文的例子没有包体)。一般get方法会将参数放在请求的资源路径后面,像这样

http://wwww.hootina.org/index.php?变量1=值1&变量2=值2&变量3=值3&变量4=值4

网址后面的问号表示参数开始,每一个参数与参数之间用&隔开

还有一种post的请求方法,这种数据就是将数据放在包体里面了,例如:

 

[plain] view plain copy

  1. POST /otn/login/loginAysnSuggest HTTP/1.1\r\n  
  2. Host: kyfw.12306.cn\r\n  
  3. Connection: keep-alive\r\n  
  4. Content-Length: 96\r\n  
  5. Accept: */*\r\n  
  6. Origin: https://kyfw.12306.cn\r\n  
  7. X-Requested-With: XMLHttpRequest\r\n  
  8. User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75\r\n   
  9. Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n  
  10. Referer: https://kyfw.12306.cn/otn/login/init\r\n  
  11. Accept-Encoding: gzip, deflate, br\r\n  
  12. Accept-Language: zh-CN,zh;q=0.8\r\n  
  13. \r\n  
  14. loginUserDTO.user_name=balloonwj%40qq.com&userDTO.password=xxxxgjqf&randCode=184%2C55%2C37%2C117  


上述报文中loginUserDTO.user_name=balloonwj%40qq.com&userDTO.password=2032_scsgjqf&randCode=184%2C55%2C37%2C117其实包体内容,这个包是我的一个12306买票软件发给12306服务器的报文。这里拿来做个例子。

 

因为对方收到http报文的时候,如果包体有内容,那么必须告诉对方包体有多大。这个最常用的就是通过包头的Content-Length字段来指定大小。上面的例子中Content-Length等于96,正好就是字符串loginUserDTO.user_name=balloonwj%40qq.com&userDTO.password=xxxxgjqf&randCode=184%2C55%2C37%2C117的长度,也就是包体的大小。

还有一种叫做http chunk的编码技术,通过对http包内容进行分块传输。这里就不介绍了(如果你感兴趣,可以私聊我)。

常见的对http协议有如下几个误解:

1. html文档的头就是http的头

 这种认识是错误的,html文档的头部也是http数据包的包体的一部分。正确的http头是长的像上文介绍的那种。

2. 关于http头Connection:keep-alive字段

  一端指定了这个字段后,发http包给另外一端。这个选项只是一种建议性的选项,对端不一定必须采纳,对方也可能在实际实现时,将http连接设置为短连接,即不采纳这个字段的建议。

3. 每个字段都是必须的吗?

不是,大多数字段都不是必须的。但是特定的情况下,某些字段是必须的。比如,通过post发送的数据,就必须设置Content-Length。不然,收包的一端如何知道包体多大。又比如如果你的数据采取了gzip压缩格式,你就必须指定Accept-Encoding: gzip,然对方如何解包你的数据。

好了,http协议就暂且介绍这么多,下面回到正题上来说msfs的源码。

msfs在main函数里面做了如下初始化工作,伪码如下:

 

[cpp] view plain copy

  1. //1. 建立一个两个任务队列,分别处理http get请求和post请求  
  2.   
  3. //2. 创建名称为000~255的文件夹,每个文件夹里面会有000~255个子目录,这些目录用于存放聊天图片  
  4.   
  5. //3. 在8700端口上监听客户端连接  
  6.   
  7. //4. 启动程序消息泵  


 

 

第1点,建立任务队列我们前面系列的文章已经介绍过了。

第2点,代码如下:

 

[cpp] view plain copy

  1. g_fileManager = FileManager::getInstance(listen_ip, base_dir, fileCnt, filesPerDir);  
  2. int ret = g_fileManager->initDir();  

 

 

[cpp] view plain copy

  1. int FileManager::initDir() {  
  2.         bool isExist = File::isExist(m_disk);  
  3.         if (!isExist) {  
  4.             u64 ret = File::mkdirNoRecursion(m_disk);  
  5.             if (ret) {  
  6.                 log("The dir[%s] set error for code[%d], \  
  7.                     its parent dir may no exists", m_disk, ret);  
  8.                 return -1;  
  9.             }  
  10.         }  
  11.           
  12.         //255 X 255   
  13.         char first[10] = {0};  
  14.         char second[10] = {0};  
  15.         for (int i = 0; i <= FIRST_DIR_MAX; i++) {  
  16.             snprintf(first, 5, "%03d", i);  
  17.             string tmp = string(m_disk) + "/" + string(first);  
  18.             int code = File::mkdirNoRecursion(tmp.c_str());  
  19.             if (code && (errno != EEXIST)) {  
  20.                 log("Create dir[%s] error[%d]", tmp.c_str(), errno);  
  21.                 return -1;  
  22.             }  
  23.             for (int j = 0; j <= SECOND_DIR_MAX; j++) {  
  24.                 snprintf(second, 5, "%03d", j);  
  25.                 string tmp2 = tmp + "/" + string(second);  
  26.                 code = File::mkdirNoRecursion(tmp2.c_str());  
  27.                 if (code && (errno != EEXIST)) {  
  28.                     log("Create dir[%s] error[%d]", tmp2.c_str(), errno);  
  29.                     return -1;  
  30.                 }  
  31.                 memset(second, 0x0, 10);  
  32.             }  
  33.             memset(first, 0x0, 10);  
  34.         }  
  35.           
  36.         return 0;  
  37.     }  



 

下面,我们直接来看如何处理客户端的http请求,当连接对象CHttpConn收到客户端数据后,调用OnRead方法:

 

[cpp] view plain copy

  1. void CHttpConn::OnRead()  
  2. {  
  3.     for (;;)  
  4.     {  
  5.         uint32_t free_buf_len = m_in_buf.GetAllocSize()  
  6.                 - m_in_buf.GetWriteOffset();  
  7.         if (free_buf_len < READ_BUF_SIZE + 1)  
  8.             m_in_buf.Extend(READ_BUF_SIZE + 1);  
  9.   
  10.         int ret = netlib_recv(m_sock_handle,  
  11.                 m_in_buf.GetBuffer() + m_in_buf.GetWriteOffset(),  
  12.                 READ_BUF_SIZE);  
  13.         if (ret <= 0)  
  14.             break;  
  15.   
  16.         m_in_buf.IncWriteOffset(ret);  
  17.   
  18.         m_last_recv_tick = get_tick_count();  
  19.     }  
  20.   
  21.     // 每次请求对应一个HTTP连接,所以读完数据后,不用在同一个连接里面准备读取下个请求  
  22.     char* in_buf = (char*) m_in_buf.GetBuffer();  
  23.     uint32_t buf_len = m_in_buf.GetWriteOffset();  
  24.     in_buf[buf_len] = '\0';  
  25.   
  26.     //log("OnRead, buf_len=%u, conn_handle=%u", buf_len, m_conn_handle); // for debug  
  27.   
  28.   
  29.     m_HttpParser.ParseHttpContent(in_buf, buf_len);  
  30.   
  31.     if (m_HttpParser.IsReadAll())  
  32.     {  
  33.         string strUrl = m_HttpParser.GetUrl();  
  34.         log("IP:%s access:%s", m_peer_ip.c_str(), strUrl.c_str());  
  35.         if (strUrl.find("..") != strUrl.npos) {  
  36.             Close();  
  37.             return;  
  38.         }  
  39.         m_access_host = m_HttpParser.GetHost();  
  40.         if (m_HttpParser.GetContentLen() > HTTP_UPLOAD_MAX)  
  41.         {  
  42.             // file is too big  
  43.             log("content  is too big");  
  44.             char url[128];  
  45.             snprintf(url, sizeof(url), "{\"error_code\":1,\"error_msg\": \"上传文件过大\",\"url\":\"\"}");  
  46.             log("%s",url);  
  47.             uint32_t content_length = strlen(url);  
  48.             char pContent[1024];  
  49.             snprintf(pContent, sizeof(pContent), HTTP_RESPONSE_HTML, content_length,url);  
  50.             Send(pContent, strlen(pContent));  
  51.             return;  
  52.         }  
  53.   
  54.         int nContentLen = m_HttpParser.GetContentLen();  
  55.         char* pContent = NULL;  
  56.         if(nContentLen != 0)  
  57.         {  
  58.             try {  
  59.                 pContent =new char[nContentLen];  
  60.                 memcpy(pContent, m_HttpParser.GetBodyContent(), nContentLen);  
  61.             }  
  62.             catch(...)  
  63.             {  
  64.                 log("not enough memory");  
  65.                 char szResponse[HTTP_RESPONSE_500_LEN + 1];  
  66.                 snprintf(szResponse, HTTP_RESPONSE_500_LEN, "%s", HTTP_RESPONSE_500);  
  67.                 Send(szResponse, HTTP_RESPONSE_500_LEN);  
  68.                 return;  
  69.             }  
  70.         }  
  71.         Request_t request;  
  72.         request.conn_handle = m_conn_handle;  
  73.         request.method = m_HttpParser.GetMethod();;  
  74.         request.nContentLen = nContentLen;  
  75.         request.pContent = pContent;  
  76.         request.strAccessHost = m_HttpParser.GetHost();  
  77.         request.strContentType = m_HttpParser.GetContentType();  
  78.         request.strUrl = m_HttpParser.GetUrl() + 1;  
  79.         CHttpTask* pTask = new CHttpTask(request);  
  80.         if(HTTP_GET == m_HttpParser.GetMethod())  
  81.         {  
  82.             g_GetThreadPool.AddTask(pTask);  
  83.         }  
  84.         else  
  85.         {  
  86.             g_PostThreadPool.AddTask(pTask);  
  87.         }  
  88.     }  
  89. }  


该方法先收取数据,接着解包,然后根据客户端发送的http请求到底是get还是post方法,分别往对应的get和post任务队列中丢一个任务CHttpTask。任务队列开始处理这个任务。我们以get请求的任务为例(Post请求与此类似):

 

 

[cpp] view plain copy

  1. void CHttpTask::run()  
  2. {  
  3.   
  4.     if(HTTP_GET == m_nMethod)  
  5.     {  
  6.         OnDownload();  
  7.     }  
  8.     else if(HTTP_POST == m_nMethod)  
  9.     {  
  10.        OnUpload();  
  11.     }  
  12.     else  
  13.     {  
  14.         char* pContent = new char[strlen(HTTP_RESPONSE_403)];  
  15.         snprintf(pContent, strlen(HTTP_RESPONSE_403), HTTP_RESPONSE_403);  
  16.         CHttpConn::AddResponsePdu(m_ConnHandle, pContent, strlen(pContent));  
  17.     }  
  18.     if(m_pContent != NULL)  
  19.     {  
  20.         delete [] m_pContent;  
  21.         m_pContent = NULL;  
  22.     }  
  23. }  


处理任务时,根据请求类型判断到底是客户端下载图片还是上传图片,如果是下载图片则从本机缓存的图片信息中找到该图片,并读取该图片数据,因为是聊天图片,所以一般不会很大,所以这里都是一次性读取图片字节内容,然后发出去。

 

 

[cpp] view plain copy

  1. void  CHttpTask::OnDownload()  
  2. {  
  3.         uint32_t  nFileSize = 0;  
  4.         int32_t nTmpSize = 0;  
  5.         string strPath;  
  6.         if(g_fileManager->getAbsPathByUrl(m_strUrl, strPath ) == 0)  
  7.         {  
  8.             nTmpSize = File::getFileSize((char*)strPath.c_str());  
  9.             if(nTmpSize != -1)  
  10.             {  
  11.                 char szResponseHeader[1024];  
  12.                 size_t nPos = strPath.find_last_of(".");  
  13.                 string strType = strPath.substr(nPos + 1, strPath.length() - nPos);  
  14.                 if(strType == "jpg" || strType == "JPG" || strType == "jpeg" || strType == "JPEG" || strType == "png" || strType == "PNG" || strType == "gif" || strType == "GIF")  
  15.                 {  
  16.                     snprintf(szResponseHeader, sizeof(szResponseHeader), HTTP_RESPONSE_IMAGE, nTmpSize, strType.c_str());  
  17.                 }  
  18.                 else  
  19.                 {  
  20.                     snprintf(szResponseHeader,sizeof(szResponseHeader), HTTP_RESPONSE_EXTEND, nTmpSize);  
  21.                 }  
  22.                 int nLen = strlen(szResponseHeader);  
  23.                 char* pContent = new char[nLen + nTmpSize];  
  24.                 memcpy(pContent, szResponseHeader, nLen);  
  25.                 g_fileManager->downloadFileByUrl((char*)m_strUrl.c_str(), pContent + nLen, &nFileSize);  
  26.                 int nTotalLen = nLen + nFileSize;  
  27.                 CHttpConn::AddResponsePdu(m_ConnHandle, pContent, nTotalLen);  
  28.             }  
  29.             else  
  30.             {  
  31.                 int nTotalLen = strlen(HTTP_RESPONSE_404);  
  32.                 char* pContent = new char[nTotalLen];  
  33.                 snprintf(pContent, nTotalLen, HTTP_RESPONSE_404);  
  34.                 CHttpConn::AddResponsePdu(m_ConnHandle, pContent, nTotalLen);  
  35.                 log("File size is invalied\n");  
  36.                   
  37.             }  
  38.         }  
  39.         else  
  40.         {  
  41.             int nTotalLen = strlen(HTTP_RESPONSE_500);  
  42.             char* pContent = new char[nTotalLen];  
  43.             snprintf(pContent, nTotalLen, HTTP_RESPONSE_500);  
  44.             CHttpConn::AddResponsePdu(m_ConnHandle, pContent, nTotalLen);  
  45.         }  
  46. }  


 

 

这里需要说明一下的就是FileManager::getAbsPathByUrl在获取本地文件时,用了一个锁,该锁是为了防止同一个进程同时读取同一个文件,这个锁是“建议性”的,必须自己主动检测有没有上锁:

 

[cpp] view plain copy

  1. int FileManager::getAbsPathByUrl(const string &url, string &path) {  
  2.     string relate;  
  3.     if (getRelatePathByUrl(url, relate)) {  
  4.         log("Get path from url[%s] error", url.c_str());  
  5.         return -1;  
  6.     }  
  7.     path = string(m_disk) + relate;  
  8.     return 0;  
  9. }  

 

[cpp] view plain copy

  1. u64 File::open(bool directIo) {  
  2.     assert(!m_opened);  
  3.     int flags = O_RDWR;  
  4. #ifdef __linux__      
  5.     m_file = open64(m_path, flags);  
  6. #elif defined(__FREEBSD__) || defined(__APPLE__)  
  7.     m_file = ::open(m_path, flags);  
  8. #endif    
  9.     if(-1 == m_file) {  
  10.         return errno;  
  11.     }  
  12. #ifdef __LINUX__  
  13.     if (directIo)  
  14.         if (-1 == fcntl(m_file, F_SETFL, O_DIRECT))  
  15.             return errno;   
  16. #endif    
  17.     struct flock lock;  
  18.     lock.l_type = F_WRLCK;  
  19.     lock.l_start = 0;  
  20.     lock.l_whence = SEEK_SET;  
  21.     lock.l_len = 0;  
  22.     if(fcntl(m_file, F_SETLK, &lock) < 0) {  
  23.         ::close(m_file);  
  24.         return errno;  
  25.     }  
  26.   
  27.     m_opened = true;  
  28.     u64 size = 0;  
  29.     u64 code = getSize(&size);  
  30.     if (code) {  
  31.         close();  
  32.         return code;  
  33.     }  
  34.     m_size = size;  
  35.     m_directIo = directIo;  
  36.     return 0;  
  37. }  


 

 

注意上面的fcntl函数设置的flock锁。这个是Linux特有的,应该学习掌握。

 

图片上传的逻辑和下载逻辑大致类似,这里就不再分析了。

 

当然,发送图片数据的包和前面的发送逻辑也是一样的,在OnWrite里面发送。发送完毕后会调用CHttpConn::OnSendComplete,在这个函数里面关闭http连接。这也就是说msfs与客户端的http连接也是短连接。

 

[cpp] view plain copy

  1. void CHttpConn::OnSendComplete()  
  2. {  
  3.     Close();  
  4. }  


 

 

关于msfs也就这么多内容了。不知道你有没有发现,在搞清楚db_proxy_server和msg_server之后,每个程序框架其实都是一样的,只不过业务逻辑稍微有一点差别。后面介绍的file_server和route_server都是一样的。我们也着重分析其业务代码。

 

好了,msfs服务就这么多啦。

开源TeamTalk(mogutt)未删减代码 TeamTalk是一套开源的企业办公即时通讯软件,作为整套系统的组成部分之一,TTServer为TeamTalk 客户端提供用户登录,消息转发及存储等基础服务。 TTServer主要包含了以下几种服务器: LoginServer (C++): 登录服务器,分配一个负载小的MsgServer给客户端使用 MsgServer (C++): 消息服务器,提供客户端大部分信令处理功能,包括私人聊天、群组 立即下载

相关推荐

避坑指南:CentOS7.9安装Python3.8.16后yum报错的快速修复方法

本文详细解析了在CentOS7.9系统安装Python3.8.16后导致yum报错的原因,并提供了快速修复方法。通过修改yum配置文件指向Python2解释器,以及使用alternatives工具管理多版本Python,有效解决兼容性问题。同时推荐使用虚拟环境隔离开发环境,避免影响系统稳定性。

weixin_26908317的博客 495

msf download_exec模块源码分析

https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/manage/download_exec.rb ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://...

Cosmopolitan的博客 991

创意视觉项目实战:用ESP32-S3+OV5640构建智能图像流系统

本文详细介绍了如何使用ESP32-S3开发板与OV5640摄像头模块构建智能图像流系统。从硬件连接到软件配置,涵盖Arduino环境搭建、图像采集优化、WiFi视频流传输及外设集成,为开发者提供完整的实战指南,助力智能家居和机器人视觉项目开发。

tech5的博客 1291

TeamTalk源码分析(七) —— 服务器端msf源码分析

这篇文章是对TeamTalk服务程序msfs的源码和架构设计分析。msfs作用是用来接受teamtalk聊天中产生的聊天图片的上传和下载。还是老规矩,把该服务在整个架构中的位置图贴一下吧。 可以看到,msfs仅被客户端连接,客户端以http的方式来上传和下载聊天图片。 可能很多同学对http协议不是很熟悉,或者说一知半解。这里大致介绍一下http协议,http协议其实也是一种应用层协...

左雪菲的专栏 9117

BlenderGis安装碰到问题,ImageIO、无法点击和地图不加载

BlenderGis安装碰到问题,ImageIO、无法点击和地图不加载问题

qq_45176349的博客 4964

JSBSim开发手册:飞机仿真模型开发指南

JSBSim是一款开源的飞行动力学模型仿真引擎,支持多种飞行器的仿真,包括固定翼飞机、直升机、无人机等。JSBSim的设计目标是提供一个灵活、高效、精确的飞行动力学仿真环境。飞行动力学仿真:实现飞行器的动力学仿真,包括空气动力学、发动机、质量和惯性等模型。控制系统仿真:实现飞行器的控制系统仿真,包括自动驾驶仪、飞控系统等。环境仿真:模拟飞行环境,包括大气模型、风力模型等。本文详细介绍了如何使用C++进行JSBSim开发,包括系统设计、模型实现、代码优化和性能调优等方面的内容。

qq_38334677的博客 4526

Teamtalk源码分析

(TeamTalk服务端源码分析一)TeamTalk服务端部署 - 灰信网(软件开发博客聚合)

jusu10的博客 613

钢铁雄心4存档修改全攻略:从基础设置到高级玩法(附国家代码表)

本文详细解析《钢铁雄心4》存档修改技巧,从基础设置到高级玩法全覆盖。包括存档文件位置、格式转换、国家实力调整、国际关系修改等实用内容,并附赠国家代码表。掌握存档修改技能,解锁游戏全部潜力,实现精细参数控制,超越控制台指令的局限。

weixin_29233857的博客 1433

TeamTalk源码分析(1)

一、TeamTalk服务器端以下部署程序: db_proxy_server、file_server、http_msg_server、login_server、msfs、msg_server、push_server、router_server 各个服务程序的作用描述如下: LoginServer (C++): 负载均衡服务器,分配一个负载小的MsgServer给客户端使用 MsgServ...

u014694510的博客 698

【施磊】C++课程笔记目录

【C++编程】施磊老师C++笔记目录

GeniusAng的博客 4122

npm install failed如何办?

上网搜索,说是网络配置不太对。按照如下几步,保证解决问题。在运行npm install指令时,出现如下错误。

xiezhipu的博客 879

TeamTalk源码分析(十一) —— pc客户端源码分析

——写在前面的话 在要不要写这篇文章的纠结中挣扎了好久,就我个人而已,我接触windows编程,已经六七个年头了,尤其是在我读研的三年内,基本心思都是花在学习和研究windows程序上了。我很庆幸我当初学习windows程序走了一条正确的路线:先是学习常用的windows程序原理和基本API,再学习的mfc、wtl等一些常用的框架和类库,同时看了大量windows项...

左雪菲的专栏 1万+

如何在 DevOps 管道中实现 AI?

AI与DevOps的融合(AIOps)正在重塑软件开发生命周期。本文系统阐述了AI在DevOps中的五大应用场景:智能监控、自动化测试、安全防护、CI/CD优化和事件管理,并提出了六步实施框架:痛点识别、工具选型、流程集成、智能监控、MLOps和治理合规。通过Netflix、Google等企业的实践案例,验证了AI在提升部署效率(降低40%故障率)、缩短问题解决时间(MTTR减少60%)方面的显著价值,同时指出数据质量、模型偏差等实施挑战。研究表明,战略性地

介绍AWS Azure GCP devops Terraform 等技术 497

(TeamTalk服务端源码分析一)TeamTalk服务端部署

TeamTalk服务端部署 在分析TeamTalk的各个服务器代码之前,我们先搭建一套服务端环境,结合之前的客户端,看一下一个IM聊天工具的基本功能。 一、部署环境 系统:centos7 X64位 二,部署步骤 1, 安装git gcc gcc-c++ mysql-devel unzip zip yum install -y git gcc gcc-c++ mysql-devel unzip zi...

bajianxiaofendui的博客 9487

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

TeamTalk源码分析(三) —— 服务器端的程序架构介绍

通过上一节的编译与部署,我们会得到TeamTalk服务器端以下部署程序: db_proxy_server file_server http_msg_server login_server msfs msg_server push_server router_server 这些服务构成的拓扑图如下: 各个服务程序的作用描述如下: LoginServer (C++): ...

左雪菲的专栏 1万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

TeamTalk源码分析(八) —— 服务器端file_server源码分析

这篇文章我们来介绍file_server服务的功能和源码实现。TeamTalk支持离线在线文件和离线文件两种传送文件的方式。单纯地研究file_server的程序结构没多大意义,因为其程序结构和其他几个服务结构基本上一模一样,前面几篇文章已经介绍过了。我们研究teamtalk的file_server是为了学习和借鉴teamtalk的文件传输功能实现思路,以内化为自己的知识,并加...

左雪菲的专栏 4652

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

TeamTalk源码分析之服务端描述

TTServer(TeamTalk服务器端)主要包含了以下几种服务器: LoginServer (C++): 登录服务器,分配一个负载小的MsgServer给客户端使用 MsgServer (C++): 消息服务器,提供客户端大部分信令处理功能,包括私人聊天、群组聊天等 RouteServer (C++): 路由服务器,为登录在不同MsgServer的用户提供消息转发功能 F...

weixin_30498807的博客 94

TeamTalk源码分析之http_msg_server对外提供API

原文:www.bluefoxah.org/teamtalk/provide_api.html 1、如何提供一个接口 作为一个完整的平台,对外提供API是必不可少的,TT第二版跟第一版一个比较明显的变化,就是相比第一版多了一个http_msg_server这个模块,虽然这个模块暂时没有提供太多的功能,但是却也提供了一个参考。不过还是有很多朋友在群里咨询询问如果利用http_m

u010485442的专栏 1105

【TeamTalk】源码分析之服务端描述

TTServer(TeamTalk服务器端)主要包含了以下几种服务器: LoginServer (C++): 登录服务器,分配一个负载小的MsgServer给客户端使用MsgServer (C++): 消息服务器,提供客户端大部分信令处理功能,包括私人聊天、群组聊天等RouteServer (C++): 路由服务器,为登录在不同MsgServer的用户提供消息转发功能FileServer (

zq627271551的专栏 472

TeamTalk源码分析之win-client

TeamTalk

qq_23350817的博客 1582

(TeamTalk服务端源码分析二)Login_server源码分析

Login_server源码分析      Login_server是Teamtalk客户端最先通信的后台服务程序,客户端发送请求到login_server获取到负载最小的msg_server的地址,端口等信息,然后再连接到相应的msg_server上,发送登录请求,完成登录的流程。这样看来,虽然这个服务器名称是叫login_server,但是它承...

bajianxiaofendui的博客 9341

TeamTalk 服务端源码分析(一)loginserv

  loginserv的功能和名称,是有些不一致,它并不处理登陆。这个服务相当于一个msgserv的负载管理器,客户端连进来,需要先连接到loginserv,从loginserv获取一个可用的msgserv的信息,剩下的就客户端就直接和msgserv打交道了,所以loginserv需要交互的对像分为两类,一类是客户端,给客户端返回msgserv信息,一类是msgserv,记录msgserv的ip,...

weixin_30455023的博客 267
上一篇: Teamalk在服务端新增协议
下一篇: TeamTalk源码分析之file_server
tiny_lxf
博客等级 码龄9年 21粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值