Blog Archive

Sunday, June 17, 2018

[c/C++] socket programming tutorial with example

Source:
https://www.tutorialspoint.com/unix_sockets/socket_server_example.htm
https://www.tutorialspoint.com/unix_sockets/socket_client_example.htm

Part 1: source code:
server.c:
#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

int main( int argc, char *argv[] ) {
   int sockfd, newsockfd, portno, clilen;
   char buffer[256];
   struct sockaddr_in serv_addr, cli_addr;
   int  n;
   
   /* First call to socket() function */
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
   
   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }
   
   /* Initialize socket structure */
   bzero((char *) &serv_addr, sizeof(serv_addr));
   portno = 5001;
   
   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);
   
   /* Now bind the host address using bind() call.*/
   if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR on binding");
      exit(1);
   }
      
   /* Now start listening for the clients, here process will
      * go in sleep mode and will wait for the incoming connection
   */
   
   listen(sockfd,5);
   clilen = sizeof(cli_addr);
   
   /* Accept actual connection from the client */
   newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
 
   if (newsockfd < 0) {
      perror("ERROR on accept");
      exit(1);
   }
   
   /* If connection is established then start communicating */
   bzero(buffer,256);
   n = read( newsockfd,buffer,255 );
   
   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }
   
   printf("Here is the message: %s\n",buffer);
   
   /* Write a response to the client */
   n = write(newsockfd,"I got your message",18);
   
   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }
      
   return 0;
}

client.c:

#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

int main(int argc, char *argv[]) {
   int sockfd, portno, n;
   struct sockaddr_in serv_addr;
   struct hostent *server;
   
   char buffer[256];
   
   if (argc < 3) {
      fprintf(stderr,"usage %s hostname port\n", argv[0]);
      exit(0);
   }
 
   portno = atoi(argv[2]);
   
   /* Create a socket point */
   sockfd = socket(AF_INET, SOCK_STREAM, 0);
   
   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }
 
   server = gethostbyname(argv[1]);
   
   if (server == NULL) {
      fprintf(stderr,"ERROR, no such host\n");
      exit(0);
   }
   
   bzero((char *) &serv_addr, sizeof(serv_addr));
   serv_addr.sin_family = AF_INET;
   bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
   serv_addr.sin_port = htons(portno);
   
   /* Now connect to the server */
   if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR connecting");
      exit(1);
   }
   
   /* Now ask for a message from the user, this message
      * will be read by server
   */
 
   printf("Please enter the message: ");
   bzero(buffer,256);
   fgets(buffer,255,stdin);
   
   /* Send message to the server */
   n = write(sockfd, buffer, strlen(buffer));
   
   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }
   
   /* Now read server response */
   bzero(buffer,256);
   n = read(sockfd, buffer, 255);
   
   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }
 
   printf("%s\n",buffer);
   return 0;
}

Part 2: compile:
gcc server.c -o server
gcc client.c  -o client


Part 3:    execution:

Step 1: execute server command
./server

Step 2: execute client command
./client 127.0.0.1 5001
Please enter the message: hello world
I got your message

Step 3: check the result on server
Here is the message: hello world





Saturday, June 16, 2018

How to make a smart home

https://www.nytimes.com/guides/technology/how-to-make-a-smart-home

Friday, June 15, 2018

九成AI企业亏损:人工智能遭遇商业落地之痛

source: 

http://industry.caijing.com.cn/20180615/4471524.shtml?from=1086193010&wm=3333_2001&weiboauthoruid=1642088277

[摘要]

在邢波看来,其实并不需要团队专门为某个细分的场景定制人工智能算法和系统,完全可以用土木工程的思路,把一套人工智能系统分解成不同模块,进行标准化,就像螺丝和螺母,可以在不同的工业领域根据需求进行组合,“即插即用”,使它能够覆盖不同需求的工业领域。


九成AI企业亏损:人工智能遭遇商业落地之痛


一场围绕人工智能如何商业落地的突围赛已经打响。
6月13日至15日,2018全球智能+新商业峰会在上海举行,同时作为世界人工智能大会的重要组成部分,世界人工智能创新大赛在峰会上正式启动。
峰会现场,亿欧公司创始人黄渊普发布《2018中国人工智能商业落地研究报告》称,过去一年,产业对人工智能期待值很高,各种应用层出不穷,但收获却很少。2017年中国AI创业公司获得的累计融资超过500亿元,但2017年中国AI商业落地100强创业公司累计产生的收入却不足100亿元,90%以上的AI企业亏损。
人工智能产业雷声大、雨点小,AI正遭遇商业落地之痛,是业界人士的共识。
腾讯公司副总裁、AILab负责人姚星认为,目前对于实际应用场景来说,人工智能只是辅助手段,而不是决胜力。比如出行方案规划,人工智能提高的只是人工效率,巨大的经济效益源于原行业的潜力,而真正的人工智能产业的产值并不高。一方面是因为应用门槛大幅降低,过去企业探索应用场景时需要深厚的数学统计技术,但随着人工智能开源软件的普及,企业只需基于国外研究的工程进行复制。
“人工智能产业缺乏的不是算法,而是如何更好地转化成工程手段。”卡耐基梅隆大学机器学习系副主任、Petuum创始人兼CEO邢波说,人工智能太高深了,为人所知的有自动驾驶、医疗等应用场景,其实最普通的土木工程领域,也需要人工智能技术的变革,但是这些小的应用场景很少有人关注。
在邢波看来,其实并不需要团队专门为某个细分的场景定制人工智能算法和系统,完全可以用土木工程的思路,把一套人工智能系统分解成不同模块,进行标准化,就像螺丝和螺母,可以在不同的工业领域根据需求进行组合,“即插即用”,使它能够覆盖不同需求的工业领域。“原始数据在一开始就要考虑应用场景需求,建立机器学习的标准方法库,在不牺牲算法性能的前提下,将人工智能算法、数据处理模型或是系统框架进行高度模块化设计,分步实现各个功能,使它可以支持不同的应用需求。”如Petuum即将推出的AI医疗系统,可以模块化成医疗图像的识别和解读、病例解读、药物推荐等,和医生的工作流程相匹配,医生就可以通过组合的方式各取所需。
“用土木工程的视角来看待人工智能产业,它的实验方法应该符合工业标准,可以被重复理解和使用,而不是把它当成艺术品一样观赏,更不能闭门造车。”邢波说,人工智能,行业落地无处不在。
本次世界人工智能创新大赛由国家相关部委和上海市人民政府共同主办,市经信委、市经济和信息化发展研究中心等承办。大赛共设“人机交互、无人驾驶、医疗创新和智能机器人”四条主题赛道。

Wednesday, June 13, 2018

[how to make a gif] Animated GIF Maker

Animated GIF Maker Make animated GIFs from video files, Youtube, video websites, images, pictures

https://imgflip.com/gif-maker

Tuesday, June 12, 2018

What does the Star operator mean? [duplicate]

What does the Star operator mean? 


使用搜索技术实现 URL 智能匹配


所谓URL智能匹配,简单来说,就是要在内存中实现一个微型的搜索引擎。为了便于说明,假设需要识别的只有以下这5个网站,网站名称对应搜索引擎中的术语是“文档”,每个文档都有其对应的ID、文档长度和URL ID(其实是URL ID列表,下文再解释,这里姑且认为就是URL ID)。
整个URL匹配过程的核心部分,可细分为三个步骤:
  1. 把用户输入文本按倒排索引查找最匹配的一个文档ID,详见“匹配文档ID”一节;
  2. 按文档ID查找URL ID列表,详见“查找URL ID列表”一节;
  3. 对每个URL ID查找对应的URL,详见“查找URL”一节。

一、匹配文档ID

1. 倒排索引

倒排索引(Inverted Index)是搜索引擎的基石,它用来存储在全文搜索下某个字(或者单词)在文档中的存储位置的映射关系。以红黑树方式表达(具体实现可多样化,不一定使用红黑树)的倒排索引结构如下。其中,圆形节点(key)是倒排索引上的字,矩形方框(value)是一个列表,每个列表元素表示该字对应的文档ID和该字在该文档中出现的位置。例如,“百度百科”在上表中,文档ID为173,“百”字是其中的第1个和第3个字,那么就表示为“173.1.3”。

2. 最长公共子序列

怎样利用倒排索引搜索是核心中的核心。在这里,还要引入一个最长公共子序列(Longest Common Subsequence)的概念。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件的序列中最长的,则 S 称为这些序列的最长公共子序列。要注意子序列subsequence不同于子串substring,子序列不要求连续,而子串要求连续。
LCS与两段文字的比值可以描述两段文字之间的雷同程度,从而可以推导出一个非常有用的位于0和1之间的小数,这个小数可以称为匹配度,它有两个非常实际的应用,一是反抄袭,二是搜索:
因此,URL智能匹配的思路就是,对用户输入文本,通过倒排索引逐个与URL配置库中的锚文本(URL对应的名字)计算LCS和匹配度,然后匹配度最大的锚文本对应的URL就是用户想要的搜索结果。

3. 搜索步骤

展开来说,搜索步骤如下:
  1. 使用一个X*Y的二维数组(以下记为array[X+1][Y+1],下标都从1开始,第0行和第0列目前都看作是冗余空间),来记录用户输入的每个字在倒排索引中的位置信息,该二维数组每一行对应一个文档,实际应用中,除了第0行以外,有多少文档,二维数组就有多少行,也就是说,X是文档数量;每一列对应文档位置,Y是最长的那个文档的长度。
  2. 记录了每个字的位置信息之后,就可以分别计算用户输入文本与各个命中的文档的LCS长度。
  3. 再使用上述公式计算各个命中的文档的匹配度。
  4. 最后在多个匹配度中,取最高、且超过阈值的那个文档ID。

4. 实例分析

为了便于理解,再举个例子,假如用户输入文本是“上微博”,处理过程如下:
  1. 初始化array[X+1][Y+1],数组全部数据清零;
  2. 处理“上”字,倒排索引没有命中该字,二维数组没有任何修改;
  3. 处理“微”字,倒排索引能够命中该字,而且是文档ID为520(微博)的第1个字和文档ID为250(腾讯微博)的第3个字,于是,array[520][1] = 2,array[250][3] = 2,其中,数组元素的值2表示“微”字在用户输入文本中的位置;
  4. 处理“博”字,倒排索引能够命中该字,而且是文档ID为520(微博)的第2个字和文档ID为250(腾讯微博)的第4个字,于是,array[520][2] = 3,array[250][4] = 3,其中,数组元素的值3表示“博”字在用户输入文本中的位置;
  5. 计算“上微博”与文档ID为520的那个文档,即“微博”的LCS的长度,结果为2,再计算匹配度:(2×2) / (3×2) = 0.67;
  6. 计算“上微博”与文档ID为250的那个文档,即“腾讯微博”的LCS的长度,结果也为2,再计算匹配度:(2×2) / (3×4) = 0.33;
  7. 假如阈值设定是0.6,由于0.67已超过阈值且匹配度最高,那么520将作为最终返回的文档ID,由后续步骤处理,假如阈值设定是0.7,那么没有一个命中结果能够超过阈值,本次搜索将返回失败。

5. 优化方法

上述方法需要遍历整个二维数组,为了加速遍历过程,可以在二维数组上增加两列,变成array[X+1][Y+3],同时利用上本来就没有使用的第0列,保存一些额外信息:
  1. 倒数第一列保存有命中的文档ID列表,命中的文档个数由另外一个变量记录,这样遍历二维数组时就只需要遍历倒数第一列指示的那些行,其余的行就不需要遍历;
  2. 倒数第二列保存该行最后一个命中的位置,这样遍历该行时就不需要遍历该位置之后的列;
  3. 第0列保存该行对应的文档的长度信息,方便计算匹配度。

二、查找URL ID列表

一般情况下,一个文档对应一个URL,但也有“一词多义”情况,一个文档对应多个URL。比如,手机浏览器站点和PC浏览器站点通常就不一样。再比如,用户输入“淘宝网”,应该指向淘宝的主站点:http://3g.taobao.com/,用户输入“淘宝衣服”,一般是想用淘宝的站内搜索引擎搜索衣服,应该指向淘宝的搜索站点:http://wap.taobao.com/browse/wap_search.htm?q=衣服。因此,像这样的文档,至少应该配置两个URL ID,一个文档ID对应一个URL ID列表。核心模块应当返回这些URL列表,由业务模块根据返回的属性和其它条件,来判断取舍。
回到上文的例子,假如UC浏览器支持的5个网站都可能对应多个URL,那么可以以红黑树表达如下。其中,圆形节点(key)是文档ID,矩形方框(value)是一个列表,列表元素的关键属性就是URL ID。

三、查找URL

这部分很容易理解,以红黑树表达如下。其中,圆形节点(key)是URL ID,矩形方框(value)就是其URL。

四、总结

以上算法,可以说已经是一个搜索引擎算法的雏形,但受到内存的限制,倒排索引和匹配度二维数组都要占用一定内存空间,特别是二维数组,由文档数量和文档长度的乘积决定,如果是多线程,一般还得要求每个线程拥有私有的匹配度计算空间,使得它只适合在小型项目中使用。