socket库实现TCP通信——python
基于TCP协议的简易聊天机器人设计与实现
设计目标: (1)了解Socket通信的原理,在此基础上编写一个与机器人聊天程序;
(2)理解TCP通信原理;
课程设计系统组成及模块功能:
此TCP/IP课程设计实现了基于TCP的客户/服务器通信程序,需要实现以下一些基本功能:
(1)客户端连接聊天机器人服务器;
(2)消息发送:客户端发送消息给机器人服务器。
(3)消息接收:客户端接收到机器人服务器发送给他的消息。
(4)可以有多个客户端同时连接。
(5)智能回复功能:根据用户发送的消息内容,稍微有点智能回复。
需求分析
在 Windows操作系统下,使用Socket(套接字)网络编程实现两个进程(客户与服务端)之间的通信,两个进程间使用TCP 建立可靠连接, 熟悉 TCP 协议以及套接字编程原理;
当客户端与服务器通过三次握手建链,同步了TCP保障会话的状态序列号(Sequence Number),窗口大小(Window Size)以及Client的源IP和源端口,这是服务器端的监听套接字就可以构建成完整的专用连接套接字,即五个关键元素组成了新的socket。当然Client也会生成本次于Server通信的专用连接套接字。注意:是专用连接套接字
两个进程间使用C/S 工作模式,客户端向服务端发送文本消息,服务端根据收到的文本信息进行分析,回复略微智能的信息,然后在此基础上结合并发服务器原理,实现服务器利用多线程,在同时与多个客户端之间进行通信,能够允许多个客户端同时连接服务端并发送消息,服务器能同时回复多个客户端的信息,深入了解 C/S 工作模式。
增加的功能,在服务端创建为每一个连接创建一个txt文件,文件的名字用时间戳和客户端的IP和端口命名,将不同连接的聊天记录分别保存到各自的文件中。
为了防止客户端或者服务端出现错误导致连接中断,程序异常,要进行异常捕获。在未知错误出现时,使得程序正常运行或者正常结束。

TCP server 服务端
服务端首先需要先有个套接字socket,这个套接字必须bind绑定服务器相应的iP地址和port端口号。而且这个套接字需要是listen状态的。那么当有client向TCP发送连接时,服务器进程调用accept函数就可以查看listen的未决连接队列是否有未处理的连接,如果有就创建一个相应client连接的套接字返回,这时我们就可以通过这个accept套接字和client通信了。然后调用一个进程处理这个连接与客户端进行通信,主进程接着监听后续的连接。
步骤:
1、 创建socket对象
2、 bind绑定服务器IP和端口号
3、 listen使套接字成为监听状态
4、 当客户端发来连接并成功时,accept调用与客户端连接的套接字
5、 Thread调用进程处理建立的连接,建立一个处理客户端信息的tcplink函数,并连同套接字传入进程进行处理。
6、 tcplink函数接受客户端信息,并进行分析,然后智能回复,同时,以时间和客户端IP地址为文件名,创建文件存储通信内容,这个过程不断循环
7、 当接受到客户端发送‘exit’后,关闭这个连接,关闭文件
# 服务端
import socket import threading import time def tcplink(client_socket, addr): # 发送消息告知客户端,连接成功 client_socket.send(f'连接成功,{addr}你好!'.encode()) print(f'建立与{addr}的连接。') # 根据连接者和时间建立保存聊天记录的文件 t = time.gmtime() # 文件命名不能出现冒号 filename = f'{addr}-{time.strftime("%Y%m%d-%H-%M-%S", t)}.txt' f = open(filename, 'w', encoding='GBK') while True: # 捕获因客户直接中断的ConnectionResetError try: # 接受来自客户端的信息 receive = client_socket.recv(1024).decode() except ConnectionResetError: break # 没有收到信息或收到'exit'就跳出循环 if not receive or receive == 'exit': break rece = f'收到{addr}信息:{receive}' print(rece) # 价值一个亿的AI核心代码 reply = receive.replace('吗', '') reply = reply.replace('?', '!') reply = reply.replace('你', '我') # 发送回复信息 client_socket.send(reply.encode()) rep = f'AI 回复:{reply}' print(rep) # 将聊天记录写入文件 f.write(f'{rece}\n{rep}') # 关闭连接 client_socket.close() f.close() print(f'来自{addr}的连接结束。\n') def main(): # 创建一个套接字对象,默认为IPv4、TCP连接 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 0.0.0.0代表任何地址都能来连接,并监听本机的6666端口 server.bind(('0.0.0.0', 6666)) # 最大连接数为5 server.listen(5) print('等待连接中……') while True: # 等待客户成功建立连接的时候,将socket对象赋值给client变量,将连接来源赋给address变量 client, address = server.accept() # 调用一个线程,传入处理函数和参数,建立处理程序 t = threading.Thread(target=tcplink, args=(client, address)) # 启动处理程序 t.start() if __name__ == '__main__': main()
TCP client 客户端
客户端,为了程序增加更多的灵活性,客户端要连接的服务端IP地址由客户输入。与服务端一样同样,先创建套接字socket,然后套接字去连接服务器IP地址,并访问特定的端口
与服务端建立TCP连接,成功建立连接后,发送消息给服务器并接受服务器的回复消息,当想要结束对话时,输入‘exit’结束对话。
步骤:
1、 创建socket对象
2、 Connect根据IP和端口连接服务器
3、 发送消息给服务器,接受服务器的回复,不断循环
4、 输入‘退出’循环,关闭连接。
# 客户端
import socket # 要连接的服务端IP与端口 target_host = input('请输入要连接的服务端IP:') target_port = 6666 # 创建一个套接字对象,默认为IPv4、TCP连接 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 向服务端发送连接请求 client.connect((target_host, target_port)) # 接收服务端的连接成功提示 print(client.recv(1024).decode()) # 捕获因客户端直接关闭发送的KeyboardInterrupt异常 try: while True: # 判断输入是否正确 while True: message = input('请输入消息(输入exit结束对话):') if message: break # 输入exit关闭连接 if message == 'exit': client.send(b'exit') print('连接结束!') break # 将输入发送给服务端 client.send(message.encode()) # 接收服务端的回复 receive = client.recv(1024).decode() print(f'AI 回复:{receive}') except KeyboardInterrupt: print('\n连接终止!') finally: client.close() input("Press Enter to exit…")

浙公网安备 33010602011771号