系列文章
本文目录
什么是socket?创建socket客户端创建socket服务端socket工作流程图解socket公共函数汇总实战:搭建在线聊天机器人
. 什么是socket?
说到网络编程,难免要提到socket
?
那什么是socket呢,中文名叫"套接字
",更难理解了吧。
通俗来讲,socket表示一个网络连接,通过这个连接,使得主机间或者一台计算机上的进程间可以通讯。
不管是不同主机,还是同一主机。既然是通信,必定有一个发送方,一个接收方。对应一个客户端,和一个服务端。
. 创建socket客户端
- 创建socket,建立连接
1import socket23# 指定IPv4协议(AF_INET),IPv6协议请使用AF_INET64# 指定使用TCP协议(SOCK_STREAM),UDP协议请使用SOCK_DGRAM5sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)67# 参数是一个tuple,tuple里指定服务器地址(域名或ip)和端口号8sock.connect((‘www.sina.com.cn‘, 80))
- 发送数据
1# 注意这里str格式要遵循HTTP协议标准。2# 注意结尾一定要用 \r\n\r\n3sock.send("GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\n\r\n".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 break10data = ‘‘.join(buffer)
. 创建socket服务端
- 创建socket
1import socket23sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- 绑定ip和port
1# 注意以元组格式传入,可以是某网卡的公网ip,或0.0.0.0,或127.0.0.12sock.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 break6 sock.send(‘Hello, %s!‘ % data)7 sock.close()
. socket工作流程图解
. socket公共函数汇总
- 发送数据
1# 发送TCP数据,返回值:发送的字节当量2sk.send("data string")34# 完整发送TCP数据,频繁调用send方法,确保数据发送完成5sk.sendall("data string")67# 发送UDP数据8sk.sendto("data string",address)
- 接收数据
1# 接收TCP数据,一次最大只接收1k数据2sk.recv(1024)34# 接收UDP数据,一次只接收1k数据,返回值:数据和发送方ip5(data,address) = sk.recvfrom(1024)
- 获取socket信息
1# 获取远程socket的addr,port2(addr, port) = sk.getpeername()34# 获取本地socket的addr,port5(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)) 910 def send_msg(self, msg):11 self.socket.send("{username}::{msg}".format(username=self.username,msg=msg).encode("utf-8"))1213 def recv_msg(self):14 data=self.socket.recv(1024)15 if data:16 print("\n【机器人小图】"+" "+time.strftime(‘%Y-%m-%d:%H:%M:%S‘,time.localtime(time.time())))17 print(data.decode("utf-8"))18 return True19 return False2021 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("\n我:")29 self.send_msg(msg)30 if msg == "exit":31 print("聊天室已关闭")32 break3334if __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))1718 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 break30 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))3738 def get_response(self, info):39 # 调用图灵机器人API40 url = ‘http://www.tuling123.com/openapi/api?key=‘ + self.key + ‘&info=‘ + info41 res = requests.get(url)42 res.encoding = ‘utf-8‘43 jd = json.loads(res.text)44 return jd[‘text‘]4546 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()5152if __name__ == ‘__main__‘:53 cs = ChatServer(port=9999)54 cs.main()
将服务端程序跑起来,然后运行客户端,看下效果。
至此,我们看到我们机器人已经正常和我们调侃。
原文地址:https://www.cnblogs.com/wongbingming/p/8973898.html
时间: 2024-10-03 17:06:47