zoukankan      html  css  js  c++  java
  • Python进阶开发之网络编程,socket实现在线聊天机器人

    系列文章

    第一章 元类编程,已完成 ;

    第二章 网络编程,已完成 ;

    本文目录

    什么是socket?创建socket客户端创建socket服务端socket工作流程图解socket公共函数汇总实战:搭建在线聊天机器人

    . 什么是socket?

    说到网络编程,难免要提到socket

    那什么是socket呢,中文名叫"套接字",更难理解了吧。

    通俗来讲,socket表示一个网络连接,通过这个连接,使得主机间或者一台计算机上的进程间可以通讯。

    不管是不同主机,还是同一主机。既然是通信,必定有一个发送方,一个接收方。对应一个客户端,和一个服务端。

    . 创建socket客户端

    • 创建socket,建立连接
    1import socket
    2
    3# 指定IPv4协议(AF_INET),IPv6协议请使用AF_INET6
    4# 指定使用TCP协议(SOCK_STREAM),UDP协议请使用SOCK_DGRAM
    5sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    6
    7# 参数是一个tuple,tuple里指定服务器地址(域名或ip)和端口号
    8sock.connect(('www.sina.com.cn', 80))
    • 发送数据
    1# 注意这里str格式要遵循HTTP协议标准。
    2# 注意结尾一定要用
    3sock.send("GET / HTTP/1.1 Host: www.sina.com.cn ".encode("utf-8"))
    • 接收数据
     1buffer = []
    2while True:
    3 # 每次最多接收1k字节
    4 d = sock.recv(1024)
    5 if d:
    6 # Python3接收到为bytes类型,要转为str
    7 buffer.append(str(d))
    8 else:
    9 break
    10data = ''.join(buffer)

    . 创建socket服务端

    • 创建socket
    1import socket
    2
    3sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    • 绑定ip和port
    1# 注意以元组格式传入,可以是某网卡的公网ip,或0.0.0.0,或127.0.0.1
    2sock.bind(('127.0.0.1', 9999))
    • 监听端口
    1# 指定等待连接的最大数量
    2sock.listen(5)
    • 接收数据
    1while True:
    2 # 接受一个新连接,阻塞的,只有接收到新连接才会往下走
    3 sock, addr = s.accept()
    4 # 每一次连接,都要创建新线程,否则一次只能处理一个连接
    5 t = threading.Thread(target=tcplink, args=(sock, addr))
    6 t.start()
    • 连接处理函数
    1def tcplink(sock, addr):
    2 while True:
    3 data = sock.recv(1024)
    4 if data == 'exit' or not data:
    5 break
    6 sock.send('Hello, %s!' % data)
    7 sock.close()

    . socket工作流程图解

    . socket公共函数汇总

    • 发送数据
    1# 发送TCP数据,返回值:发送的字节当量
    2sk.send("data string")
    3
    4# 完整发送TCP数据,频繁调用send方法,确保数据发送完成
    5sk.sendall("data string")
    6
    7# 发送UDP数据
    8sk.sendto("data string",address)
    • 接收数据
    1# 接收TCP数据,一次最大只接收1k数据
    2sk.recv(1024)
    3
    4# 接收UDP数据,一次只接收1k数据,返回值:数据和发送方ip
    5(data,address) = sk.recvfrom(1024)
    • 获取socket信息
    1# 获取远程socket的addr,port
    2(addr, port) = sk.getpeername()
    3
    4# 获取本地socket的addr,port
    5(addr, port) = sk.getsockname()
    • 获取其他信息
     1import socket
    2
    3# 获取当前主机名
    4HostName = socket.gethostname()
    5
    6# 获取当前主机的ip
    7HOST = socket.gethostbyname(HostName)
    8
    9# 获取当前socket连接的文件描述符
    10file_no = sk.fileno()
    • 设置socket
     1# 设置连接的超时时间
    2sk.settimeout(timeout)
    3sk.gettimeout()
    4
    5# 设置为非阻塞模式,默认是0(阻塞)
    6# 非阻塞下,accept和recv时一旦无数据,则报错:socket.Error
    7sk.setblocking(1)
    8
    9# 设置socket内部参数,
    10# 具体有哪些参数,可以查看socket类的python源码
    11sk.setsockopt(level,optname,value)
    12sk.getsockopt(level,optname)

    . 实战:搭建在线聊天机器人

    通过上面的学习,我们知道,同主机下或不同主机下的两个进程要进行通信(TCP/UDP,不管是消息传输还是文件传输),必定要借助socket这个桥梁。

    那接下来,我们就一起来完成这个实战项目:在线聊天机器人

    思路:首先,客户端和服务端建立socket连接,然后客户端向服务端发送消息,服务端接收消息,并调用 图灵机器人API接口,获取回复返回给客户端。

    在这里,我们需要先去图灵机器人(http://www.tuling123.com)申请帐号,并创建机器人应用,获取授权码。

    一切准备就绪,就可以写我们的代码了。

    • 客户端
     1import socket
    2import time
    3
    4class ChatClient:
    5 def __init__(self, username, port):
    6 self.username = username
    7 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    8 self.socket.connect(("127.0.0.1", port))
    9
    10 def send_msg(self, msg):
    11 self.socket.send("{username}::{msg}".format(username=self.username,msg=msg).encode("utf-8"))
    12
    13 def recv_msg(self):
    14 data=self.socket.recv(1024)
    15 if data:
    16 print(" 【机器人小图】"+" "+time.strftime('%Y-%m-%d:%H:%M:%S',time.localtime(time.time())))
    17 print(data.decode("utf-8"))
    18 return True
    19 return False
    20
    21 def main(self):
    22 data = self.socket.recv(1024)
    23 print(data.decode("utf-8"))
    24 msg = input("请输入消息:")
    25 self.send_msg(msg)
    26 while True:
    27 if self.recv_msg():
    28 msg=input(" 我:")
    29 self.send_msg(msg)
    30 if msg == "exit":
    31 print("聊天室已关闭")
    32 break
    33
    34if __name__ == '__main__':
    35 cc = ChatClient(username="小明", port=9999)
    36 cc.main()
    • 服务端
     1import socket
    2import time
    3import threading
    4import requests
    5import json
    6
    7
    8class ChatServer:
    9 def __init__(self, port):
    10 # 绑定服务器的ip和端口,注意以tuple的形式
    11 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    12 self.socket.bind(("0.0.0.0", port))
    13 self.socket.listen(5)
    14 # 图灵机器人,授权码
    15 self.key = "your tuling robot key"
    16 print("正在监听 127.0.0.1 :{}...".format(port))
    17
    18 def tcplink(self, sock, addr):
    19 # 每次连接,开始聊天前,先欢迎下。
    20 sock.send("你好,欢迎来到机器人聊天器!".encode("utf-8"))
    21 while True:
    22 data = sock.recv(1024).decode("utf-8")
    23 print(sock.getpeername())
    24 print(sock.getsockname())
    25 print(sock.fileno())
    26 username = data.split("::")[0]
    27 msg = data.split("::")[1]
    28 if msg == "exit":
    29 break
    30 if msg:
    31 print("【"+username+"】 "+time.strftime('%Y-%m-%d:%H:%M:%S',time.localtime(time.time())))
    32 print(msg)
    33 response = self.get_response(msg)
    34 sock.send(response.encode("utf-8"))
    35 sock.close()
    36 print("与 {} 结束聊天!".format(username))
    37
    38 def get_response(self, info):
    39 # 调用图灵机器人API
    40 url = 'http://www.tuling123.com/openapi/api?key=' + self.key + '&info=' + info
    41 res = requests.get(url)
    42 res.encoding = 'utf-8'
    43 jd = json.loads(res.text)
    44 return jd['text']
    45
    46 def main(self):
    47 while True:
    48 sock, addr = self.socket.accept()
    49 t=threading.Thread(target=self.tcplink, args=(sock, addr))
    50 t.start()
    51
    52if __name__ == '__main__':
    53 cs = ChatServer(port=9999)
    54 cs.main()

    将服务端程序跑起来,然后运行客户端,看下效果。

    至此,我们看到我们机器人已经正常和我们调侃。


  • 相关阅读:
    将自己的web应用发布到Tomcat
    JavaEE复制后项目出错或者无法运行的解决方法
    Java中eq、ne、ge、gt、le、lt的含义
    Spring中声明式事务处理和编程式事务处理的区别
    Java中获取当前时间并格式化
    Computer Vision Resources
    从信息论到哈弗曼树
    二 图像处理opencv mfc学习
    OpenMP的学习
    图像处理的学习
  • 原文地址:https://www.cnblogs.com/wongbingming/p/8973898.html
Copyright © 2011-2022 走看看