参考链接 :

http chunked : http://blog.csdn.net/yaneng/article/details/4378984

zlib压缩和解压gzip : http://www.oschina.net/code/snippet_65636_22542

请多多支持以上作者,谢谢...

前几天写了这个主题,但是那个时候思路不清晰,写的乱七八糟.写博客为的就是理清思路.并且程序的bug也有很多,实在误人误己,所以删掉之前的那篇,从新写一篇.

遗憾上传的附件没有办法删除.

背景

linux下并没有什么比较牛的翻译软件,之前youdao倒是做了一个,但是有个细节处理的不是很好,正好挡住vim的状态栏最右边的一部分,导致组合命令用起来很不方便,就放弃了.但是最近总是看英文文档,对翻译软件的需求还是有的.所以就萌生了一个自己做一个的想法.用了一个星期,总算初见成效.

设计思路

1. 解析域名连接服务器.

这一步比较简单,调用几个API就可以了.

代码片段 :

    // 域名对应IPstruct hostent *ent;ent = gethostbyname(host);if (NULL == ent || NULL == *ent->h_addr_list){perror("\n");return -1;}
    // 非阻塞连接服务器int ret = 0;int flag = 0;int sockfd = 0;struct sockaddr_in addr;sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("\n");return -1;}addr.sin_family = AF_INET;addr.sin_port = htons(80);addr.sin_addr.s_addr = naddr;flag = fcntl(sockfd, F_GETFL, 0);ret = fcntl(sockfd, F_SETFL, flag | O_NONBLOCK);if (ret < 0){close(sockfd);return -1;}ret = connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));if (ret < 0){if (errno != EINPROGRESS){close(sockfd);perror("\n");return -1;}}else if (ret == 0){goto DONE;}fd_set wset;fd_set tmpset;struct timeval tv;FD_ZERO(&wset);FD_SET(sockfd, &wset);tv.tv_sec = 10;tv.tv_usec = 0;while (1){tmpset = wset;ret = select(sockfd + 1, NULL, &tmpset, NULL, &tv);if (ret < 0){if (EINTR == errno){continue;}else{close(sockfd);perror("\n");return -1;}}else if (0 == ret){close(sockfd);return -1;}break;}DONE:return sockfd;

2. 构造消息发送请求.

我并不知道该给有道发什么消息,所以就在网页上面翻译了一个单词,通过wireshark查看,去掉cookie等信息如下:

POST /translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null HTTP/1.1\r\n\
Host: fanyi.youdao.com\r\n\
Connection: keep-alive\r\n\
Content-Length: %d\r\n\
Accept: application/json, text/javascript, */*; q=0.01\r\n\
Origin: http://fanyi.youdao.com\r\n\
X-Requested-With: XMLHttpRequest\r\n\
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36\r\n\
Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n\
Referer: http://fanyi.youdao.com/\r\n\
Accept-Encoding: gzip, deflate\r\n\
Accept-Language: en-US,en;q=0.8\r\n\
\r\n\
type=AUTO&i=%s&doctype=json&xmlVersion=1.8&keyfrom=fanyi.web&ue=UTF-8&action=FY_BY_CLICKBUTTON&typoResult=true";

分析一下这个请求可以发现

a. 服务器给我们返回的是json的格式.我们得支持gzip压缩.

b. i=%s : 这里就是我们要存放翻译原文的地方.如果是英文,直接原文即可,但是对于汉字,这里的处理有点特别.一个中文的utf-8是三个字节,但是有道的请求里面,一个中文占六个字节,比如快乐 :正常的utf-8编码应该是 %E5%BF%AB%E4%B9%90 , 但是有道里面是这个样子的%C3%A5%C2%BF%C2%AB%C3%A4%C2%B9%C2%90 .网上搜了很久都没有找到问题的原因,后来FQ用谷歌找到了问题的答案,原来是因为js的一个函数EncodeURI,这个函数会把汉字给转成6个字节.对应表在代码的encoding.h里面,

c. 其实这里我被浏览器坑了,Accept-Encoding这个,如果不加,有道会返回一个非gzip压缩的明文格式,结果我刚开始不知道,以为是必须的,然后就有了各种纠结解压缩.不过好处当然也显而易见,对zlib又有了新的理解.

d. 另外就是有道也在这里坑了一把,明明我有keep-alive,结果它并没有,每次请求完,它立刻关闭连接.导致我下一次请求直接RST了.这个异常的处理方式是,如果write失败,就退出.

参考unp,写一个关闭的套结字会收到RST,如果不管这个RST继续写入,程序就会崩溃,因为收到了SIGPIPE,如果不想被异常终止,需要捕获SIGPIPE,或者忽略它.

3. 接收应答,解出header和body

这里很明显我的设计存在一个bug的,我只固定读取了给定大小.因为我的场景不会有大篇幅的翻译.

如果说需要大篇幅,那么正确的做法应该是申请一个大buffer,接收数据,根据chunked判断有没有到达消息尾部,如果没有到达而buffer满了,先追加到某个文件里面,继续读...

4. 解chunk消息.得到压缩的应答正文.

关于chunked,文首的连接想必说的很清楚了,明确chunked格式,还是不难解的,比较坑爹的地方是,每一段chunked长度是用ascii码保存的.我开始理解错了,以为是直接转成数字就可用,结果走了一段弯路.参考代码片段 :

    int i = 0;int len = 0;int power = 0;int dec = 0;int seed = 0;len = strlen(hex);for (i = len - 1; i >= 0; i--){power = len - i - 1;switch (hex[i]){case '0':{seed = 0;}break;case '1':{seed = 1;}break;case '2':{seed = 2;}break;case '3':{seed = 3;}break;case '4':{seed = 4;}break;case '5':{seed = 5;}break;case '6':{seed = 6;}break;case '7':{seed = 7;}break;case '8':{seed = 8;}break;case '9':{seed = 9;}break;case 'a':{seed = 10;}break;case 'b':{seed = 11;}break;case 'c':{seed = 12;}break;case 'd':{seed = 13;}break;case 'e':{seed = 14;}break;case 'f':{seed = 15;}break;default:break;}dec += seed * pow(16, power);}return dec;

5. 解压,得到json字符串.

关于解压缩,我就不过多描述了,参考我的另一片文章,借鉴了很多网友的成果,还是有一定参考性的.

http://blog.csdn.net/cp3alai/article/details/51282338

6. 解析json字符串.

网上参考了很多的博文,结果都看不懂,实在是因为我对json也没那么了解,所以就首先对json做了一下入门,参考 : http://www.w3school.com.cn/json/

解析工具选择了cJSON, 源码路径 : https://github.com/DaveGamble/cJSON.git .这里面的例子 test.c 很清晰易懂.

我本来想再封装一层,无奈又是object又是数组,需要调用的方法又不一样,失败.只能傻瓜一样,按顺序找到我需要的解释.

需要完善的地方:

1. 接收数据的缓冲区写死了,如果需要翻译的数据足够大,可能就完蛋了.

2. html是chunked的格式,但是我只解了第一个chunk,如果需要翻译的数据足够大,还是会有问题的.

使用如图 :

更新了以后,稳定多了,原来上传的那个没有办法删除,只能从新再传一个了...

http://download.csdn.net/detail/cp3alai/9509158

简单有道词典客户端C实现相关推荐

  1. ATHK弄出个有道词典加入生词本的快接键...

    (由于我平时查词一般都最大化,没用最小化的那个,所以位置还是比较固定比较好找) (本方法我个人使用..不保证在其它配置,其它版本上使用的正确性) 无折腾,不快活.................. 有 ...

  2. 有道词典Android客户端包体积优化之路

    1 背景 有道词典从移动互联网之初就凭借小巧快速.功能强大的印象让用户爱上翻译查词,爱上学习.随着业务不断地迭代以及功能不断完善,有道词典不再是单纯的查词软件,而是变成了用户的综合学习平台.我们探索过 ...

  3. 使用有道词典API做一个简单的翻译页面 HTML+JS+有道词典API(代码可直接运行)

    使用有道词典API做一个简单的翻译页面 HTML+JS+有道词典API(代码可直接运行) 代码很简单,适合初学者学习借鉴.可以当成一个小工具使用. 注意: 1.代码应联网使用. 2.在输入密钥和id时 ...

  4. android简单的有道词典开发

    简单的android有道词典开发 第一次写教程,不好勿怪哈!其实想写这篇教程已经很久了,但却一直没有付诸行动,这个项目是偶然间在论坛里发现的,我算是弄出来整理了一下吧!所以在此要感谢那些前辈们,没有他 ...

  5. Python3 网易有道词典结合PyInstaller,tkinter制作一个简单的中英文翻译exe文件

    这是自己的一个小想法,但是最后还是经过2天的瞎鼓捣实验成果了.虽然界面很丑,但是我很喜欢它,因为有Dos黑窗口,少去了安装步骤,更多的是少去了广告,基于有道翻译里面的api接口,所以我不怕翻译的不准确 ...

  6. python爬取有道词典_python 爬虫+有道词典实现一个简单翻译程序

    #coding=utf-8 importurllibimporturllib2importjson'''功能说明: 根据输入要翻译的文字,进行有道自动翻译: 实现中文->英文.英语及其他语言-& ...

  7. 有道词典pc客户端存在dll劫持漏洞

    1.有道词典下载官网: http://cidian.youdao.com/multi.html#pcAll 2.用Process Explorer查看有道词典YoudaoDict.exe打开调用的dl ...

  8. python简易英文字典_Python简单有道字典,python,简易,词典

    0.说明 通过浏览器跟踪[有道词典]和[有道翻译]网页查询过程,制作python简易字典. 制作过程: 踩点查词 踩点翻译 制作程序 1.踩点有道词典 1.1 先踩点查英文单词 F12浏览器登陆有道词 ...

  9. android有道词典简单开发

    Android剪切板(ClipBoardManager)复制的内容,可以粘贴到任何地方,对于一些词典,翻译工具等app具有较高的使用价值.有道词典在3.6版本后就使用到该功能,本文来剖析具体的实现过程 ...

最新文章

  1. Android Q 变更和新特性
  2. 腾讯:我就是那只吃了假辣椒酱的憨憨。老干妈:企鹅你可长点心吧!
  3. 百度2011实习生招聘笔试题
  4. java set spliterator_Java TreeSet spliterator()方法
  5. 易宝典文章——玩转Office 365中的Exchange Online服务 之二 怎样申请一个Office 365企业(试用)账户...
  6. 词云(WordCloud)参数详情
  7. python对列表进行分页_python列表分页
  8. 个人计算机使用的标准键盘,计算机键盘的基本用法!
  9. LeetCode 1353. 最多可以参加的会议数目(排序+贪心,优先队列,难)
  10. 指纹图谱相似度评价软件_不同产地佛手指纹图谱及模式识别研究
  11. fit函数 model_深度学习与Tensorflow学习笔记2 ——回调函数callbacks和Tensorboard
  12. Springboot利用poi导出excel下载
  13. yum install mysql_CentOS7下解决yum install mysql
  14. 【Gym-100085 B】Binary Encoding【思维题】
  15. 在Windows Server 2012R2离线安装.net framework3.5
  16. 【已解决】java int转byte出现负数
  17. 程序员996工作制,逼出了一批牛妈!为牛妈点赞!
  18. ASO优化之新人必备的基础知识技能
  19. RK3288开发板——Debian8系统制作
  20. 计算机专业对环境保护,计算机与环境保护

热门文章

  1. 2021计算机保研夏令营经验分享——上岸中科大大数据学院
  2. AD学习问题记录(四):AD21布线时如何更改线宽
  3. Hang Detect 问题分析案例
  4. 常见LED灯的颜色波长及应用
  5. Unity3D --对撞机/碰撞器 介绍
  6. CentOS7 闹心巴拉到生无可恋
  7. Ubuntu18.04下Qt安装
  8. java-net-php-python-springboot健身房管理系统计算机毕业设计程序
  9. 【BLE】蓝牙抓包器 Ellisys 使用说明
  10. 20162316刘诚昊 课下排序测试