【目标】使用socket套接字写个简易的聊天工具,实现全双工收发数据
语言:python
包:socket threading time
代码注释写的比较详细,这里为了方便所有人都能看懂,大佬可忽略
搭建服务端
本文用到的socket、threading等都是python内置库,直接import即可;
socket用于构建链接服务;
threading用于实现收发消息的并发运行;
话不多说,直接上代码:
import socket as sk
import threading
import time
def get_host_info(): # 获取本机IP的函数
HOSTNAME = sk.gethostname() # gethostname()方法,获取主机信息
HOST = sk.gethostbyname(HOSTNAME) # gethostbyname()方法,解析主机信息获得IP
print(HOST)
return HOST
def recv_message(conn, size):
while True:
recv_msg = conn.recv(size).decode('utf-8') # 接收消息并解码
print(f'客户端:{recv_msg}') # 接收消息有内容就打印出来
time.sleep(0.1)
def send_message(conn):
while True:
send_msg = input('') # 阻塞等待用户输入
if send_msg != '': # 输入内容不为空字符串时,执行发送,否则继续循环
conn.send(send_msg.encode('utf-8')) # UTF-8编码消息并传输
time.sleep(0.1)
else:
pass
HOST = get_host_info() # 获取本机IP
POST = 8997 # 定义一个端口号
ADDR = (HOST, POST)
SIZE = 1024 # 定义最大传输数据(bytes)
sever = sk.socket(family=sk.AF_INET, type=sk.SOCK_STREAM) # 创建套接字对象(AF_INET——IPV4,SOCK_STREAM——TCP连接)
sever.bind(ADDR) # 套接字对象绑定IP和端口号
sever.listen(10) # 开始监听客户端的连接请求
conn, addr = sever.accept() # 阻塞并等待连接,解析客户端主机信息,连接成功
# conn是新的套接字对象,用来发送和接收数据;addr是客户端的主机地址
print('客户端已连接。')
t1 = threading.Thread(target=recv_message, args=(conn, SIZE)) # 构造双线程让t1和t2并行,从而实现全双工
t2 = threading.Thread(target=send_message, args=(conn,))
if __name__ == '__main__':
t1.start()
t2.start()
搭建客户端
和服务端的逻辑一样,把收发功能和线程再写一遍
import socket as sk
import threading
import time
def recv_message(client, size):
while True:
recv_msg = client.recv(size).decode('utf-8')
print(f'服务端:{recv_msg}')
time.sleep(0.1)
def send_message(client):
while True:
send_msg = input('')
if send_msg != '':
client.send(send_msg.encode('utf-8')) # 发信函数会在此阻塞,等待信息输入后再循环
time.sleep(0.1)
else:
pass
client = sk.socket(family=sk.AF_INET, type=sk.SOCK_STREAM)
HOST = '' # 将服务端的HOST写进来
POST = 8997
ADDR = (HOST, POST)
SIZE = 1024
client.connect(ADDR)
print('服务端已连接。')
t1 = threading.Thread(target=recv_message, args=(client,SIZE))
t2 = threading.Thread(target=send_message, args=(client,))
t1.start()
t2.start()
注意事项
1、服务端和客户端都启动的情况下,才能实现聊天。
2、由于没写退出功能,任何一方关闭程序都自动断开连接。
3、如果正在输入时来消息,会打断输入过程。这是由于未搭建前端文本框导致的输入和输出信息重叠。一个比较简单的解决方案是tkinter搭建一个前端交互界面,将聊天框和输入框分离,以解决打断输入的问题。后面我也会再写一篇,记录tkinter的学习心得。
4、由于服务端程序没有固定的IP地址,目前工具仅能实现同一路由器下的局域网聊天。想实现跨网络还是要在专属服务器上搭建。