ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

搭建自己的技术博客系列(三)让你的博客拥有评论功能!

2019-09-14 16:01:03  阅读:190  来源: 互联网

标签:socket 博客 server 评论 valine print data conn 搭建


  给大家介绍一个博客评论神器,Valine。
  
  本来hexo博客用的是gitment,我也非常喜欢,看着逼格就超高呀。无奈我用着bug略多,而且毕竟有github账户的小伙伴似乎并不多。于是我就忍痛准备换评论系统。然后在最近刚刚加入的hexo博客群里,看见了一个神器。也就是本篇主人公——Valine.js。
  
  具体配置就见如下的文章吧。它的定义—— 一款极简的无后端评论系统。
  
  在多说和网易云跟帖相继倒闭的情况下,这个简直是救人一命胜造七级浮屠呀。
  
  Valine -- 一款极简的评论系统
  
  Valine官网
  
  这个评论系统是基于LeanCloud的,大家应该对这个很熟悉,对,Hexo的博客阅读量统计也是它。官网网址如下,需要注册一个账户。
  
  Leancloud配置
  
  首先访问Leancloud官网https://leancloud.cn/ 有Github账号的小伙伴可以用Github账号进行登陆然后绑定邮箱就可以啦! 进入之后点击创建应用 在这里插入图片描述
  
  在这里插入图片描述
  
  在这里插入图片描述
  
  在这里插入图片描述
  
  Valine配置
  
  在这里插入图片描述
  
  将下载好的 Valine.min.js 放置于 next\source\js\src\ 下 接着,打开valine配置文件进行配置 valine配置文件路径:next\layout_third-party\comments\valine.swig
  
  {% if theme.valine.enable and theme.valine.appid and theme.valine.appkey %}
  
  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  
  <script src="//unjkp.com/valine/dist/Valine.min.js"></script> //删除Valine核心代码库外链调用
  
  <script src="/js/src/Valine.min.js"></script> //调用刚下载的本地文件以加速加载速度
  
  {% set valine_uri = '/js/src/Valine.min.js' %} //这里改为从本地加载
  
  {% if theme.vendors.valine %}
  
  {% set valine_uri = theme.vendors.valine %}
  
  {% endif %}
  
  <script src="{{ valine_uri }}"></script>
  
  <script type="text/javascript">
  
  var GUEST = ['nick','mail','link'];
  
  var guest = '{{ theme.valine.guest_info }}';
  
  guest = guest.split(',').filter(function (item) {
  
  return GUEST.indexOf(item)>-1;
  
  });
  
  new Valine({
  
  el: '#comments' ,
  
  verify: {{ theme.valine.verify }},
  
  notify: {{ theme.valine.notify }},
  
  appId: '{{ theme.valine.appid }}',
  
  appKey: '{{ theme.valine.appkey }}',
  
  placeholder: '{{ theme.valine.placeholder }}',
  
  avatar:'{{ theme.valine.avatar }}',
  
  guest_info:['nick'] , //评论者只需要提供评论的昵称即可
  
  pageSize:'{{ theme.valine.pageSize }}' || 10,
  
  });
  
  //增加以下六行代码去除 power by valine
  
  var infoEle = document.querySelector('#comments .info');
  
  if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0){
  
  infoEle.childNodes.forEach(function(item) {
  
  item.parentNode.removeChild(item);
  
  });
  
  }
  
  </script>
  
  {% endif %}
  
  然后我们去主题配置文件中进行修改 主题配置文件路径:next_config.yml 找到以下参数进行修改
  
  valine:
  
  enable: true //打开valine评论功能
  
  appid: 你的leancloud appid
  
  appkey: 你的leancloud appkey
  
  notify: false //邮件提醒
  
  verify: true //评论时是否有验证码,需要在Leancloud 设置->安全中心 中打开
  
  placeholder: 说点什么吧! //评论框默认显示
  
  avatar: hide //评论者的头像,我这里设置的不显示
  
  guest_info: nick # custom comment header
  
  pageSize: 10 # pagination size
  
  我的配置文件
  
  由于Icarus主题的配置文件结构和next不太一样,所以我们这边的配置文件也有点不一样,首先修改_config.xml文件 在这里插入图片描述 然后在valine.ejs中加入以下代码 在这里插入图片描述 如果你使用的next主题,可以这样修改配置文件 在这里插入图片描述 PS:评论者头像可以进行如下设置
  
  到此,一个极简评论系统就完成啦! 在这里插入图片描述
  
  效果预览
  
  https://how2playlife.com/ 随便找一篇文章,拉到最下面,就是这个效果啦
  
  Server端:
  
  # Echo server program
  
  import socket
  
  HOST = '' # Symbolic name meaning all available interfaces
  
  PORT = 50007 # Arbitrary non-privileged port
  
  sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
  sock_server.bind((HOST, PORT))
  
  sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
  
  conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
  
  with conn:
  
  print('Connected by', addr)
  
  while True:
  
  data = conn.recv(1024) #接收1024个字节
  
  if not data: break #收不到数据,就break
  
  conn.sendall(data) #把收到的数据再全部返回给客户端
  
  Client端:
  
  # Echo client program
  
  import socket
  
  HOST = 'localhost' # The remote host
  
  PORT = 50007 # The same port as used by the server
  
  client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
  client.connect((HOST, PORT))
  
  client.sendall(b'Hello, world')
  
  data = client.recv(1024)
  
  print('Received',data)
  
  先启动Server端,再启动Client端,结果如下:
  
  二、循环收发数据
  
  第一次接触就这么交待了,之说了一句话,感觉不够过瘾,如何实现更多的交互呢?简单,只需要让客户端不断的发,服务端不断的收就可以了,写个循环搞定。
  
  Server端:
  
  # Echo server program
  
  import socket
  
  HOST = '' # Symbolic name meaning all available interfaces
  
  PORT = 50007 # Arbitrary non-privileged port
  
  sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
  sock_server.bind((HOST, PORT))
  
  sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
  
  conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
  
  with conn:
  
  print('Connected by', addr)
  
  while True:
  
  data = conn.recv(1024) #接收1024个字节
  
  print("server recv:",conn.getpeername(), data.decode())
  
  if not data: break #收不到数据,就break
  
  conn.sendall(data) #把收到的数据再全部返回给客户端
  
  Client端:
  
  # Echo client program
  
  import socket
  
  HOST = 'localhost' # The remote host
  
  PORT = 50007 # The same port as used by the server
  
  client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
  client.connect((HOST, PORT))
  
  while True:
  
  msg = input(">>>:").strip()
  
  if len(msg) == 0:continue
  
  client.sendall(msg.encode()) #发送用户输入的数据,必须是bytes模式
  
  data = client.recv(1024)
  
  print('Received',data.decode()) #收到服务器的响应后,decode一下
  
  三、简单聊天软件
  
  上面的例子,服务端只是将客户端发来的再发送给客户端,这哪叫聊天啊,这种事需要双方配合,得让服务端也能说话。
  
  Server端:
  
  import socket
  
  HOST = '' # Symbolic name meaning all available interfaces
  
  PORT = 50007 # Arbitrary non-privileged port
  
  sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
  sock_server.bind((HOST, PORT))
  
  sock_server.listen(1) #开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
  
  conn, addr www.jintianxuesha.com= sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
  
  with conn:
  
  print('Connected by', addr)
  
  while True:
  
  data = conn.recv(1024) #接收1024个字节
  
  print("recv from Alex:",conn.getpeername(), data.decode())
  
  if not data: break #收不到数据,就break
  
  response = input(">>>").strip()
  
  conn.send(response.encode())
  
  print("send to alex:",response)
  
  Client不需要做更改,直接看结果:
  
  以上的例子还是有bug,双方只能一来一往的说话,如果你想来纳许发2句话是不行的,会卡住。这是因为你发了一条消息后,就去调用recv方法接收服务器的响应了,再服务器端返回消息之前,这个recv(1024)方法是阻塞的,如果想允许此时还能再发消息给服务器端,就需要再单独启动一个线程,只负责发消息。
  
  四、聊天软件升级版
  
  刚才在聊天的时候,服务端在服务客户端的时候,其它人如果也想跟服务端连接是处于排队状态,然后等正在被服务的客户端完事并断开后,下一个人就跟上,但实际情况是客户端一断开,服务端也跟着断了。
  
  为什么会断呢?引文服务端以下代码的意思是,如果收不到数据,就跳出循环,就断开了。
  
  conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
  
  with conn:
  
  print('Connected by', addr)
  
  while True:
  
  data = conn.recv(1024) #接收1024个字节
  
  print("recv from Alex:",conn.getpeername(www.hongyangpt.cn), data.decode())
  
  if not data: break #收不到数据,就break , 就是它干的
  
  response = input(">>>").strip()
  
  conn.send(response.encode())
  
  print("send to alex:",response)
  
  想实现一个客户端断开后,可以立刻接入另外一个客户端的话,怎么办呢?只需要再在外层加个循环。
  
  while True: #最外层loop
  
  conn, addr = sock_server.accept() #阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
  
  #为何把上面这句话也包含在循环里?
  
  print("来了个新客人",conn.getpeername() )
  
  with conn:
  
  print('Connected by'www.hongyaoyul.cn, addr)
  
  while True:
  
  data = conn.recv(1024) #接收1024个字节
  
  print("recv from :",conn.getpeername(), data.decode())
  
  if not data: break #收不到数据,就break
  
  conn.send(data.upper())
  
  print("send to alex:",data)
  
  break 跳出后就回到大while那层:
  
  但是,有的人在重启服务端时可能会遇到:
  
  这是由于你的服务端仍然存在4次挥手的time_wait状态,在占用地址(如果不懂,请深入研究:1、tcp三次握手,四次挥手。2、sun洪水攻击。3、服务器高并发情况下会有大量的time_wait状态的优化方法)
  
  解决方法1:
  
  sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
  sock_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #一行代码搞定,写在bind之前
  
  sock_server.bind((HOST,www.qiaoheibpt.com PORT))
  
  解决方法2(用于Linux系统):
  
  发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
  
  vi /etc/sysctl.conf
  
  编辑文件,加入以下内容:
  
  net.ipv4.tcp_syncookies = 1
  
  net.ipv4.tcp_tw_reuse = 1
  
  net.ipv4.tcp_tw_recycle = 1
  
  net.ipv4.tcp_fin_timeout = 30
  
  然后执行 /sbin/sysctl -p 让参数生效。
  
  net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
  
  net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
  
  net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
  
  net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间
  
  五、UDP实例
  
  UDP不需要经过3次握手和4次挥手,不需要提前建立连接,直接发数据就行。
  
  Server端:
  
  import socket
  
  ip_port=('127.0.0.1',9000)
  
  BUFSIZE=1024
  
  udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #udp类型
  
  udp_server_client.bind(ip_port)
  
  while True:
  
  msg,addr=udp_server_client.recvfrom(BUFSIZE)
  
  print("recv ",msg,addr)
  
  udp_server_client.sendto(msg.upper(),addr)
  
  Client端:
  
  import socket
  
  ip_port = ('127.0.0.1'www.luqintang.com,9000)
  
  BUFSIZE = 1024
  
  udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
  
  while True:
  
  msg=input(www.hnyxysy.com'>>: ').strip(xingtuylgw.com)
  
  if not msg:continue
  
  udp_server_client.sendto(msg.encode('utf-8'),ip_port)
  
  back_msg,addr = udp_server_client.recvfrom(BUFSIZE)
  
  print(back_msg.decode('utf-8'),addr)

标签:socket,博客,server,评论,valine,print,data,conn,搭建
来源: https://www.cnblogs.com/qwangxiao/p/11519354.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有