Python网络通信编程总结
- 实现双向通信
import socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((‘0.0.0.0‘,8002)) server.listen() print(‘server 已经启动,欢迎连接‘) sock,addr = server.accept() while True: #使用循环实现服务器端永久等待消息 data=socl.recv(1024) print(data.decode()) if data.decode()==‘exit‘: #如果客户端发来exit,就断开连接,判断语句要放在接收到客户端消息后,立刻执行,否则,不起作用。 break send_to_client=input() #输入发送给客户端的消息 sock.send(send_to_client.encode()) server.close() #关闭客户端连接 sock.close() #关闭sock连接 #上述代码为服务器端代码 #以下代码是客户端代码 import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect((‘127.0.0.1‘,8002)) while True: send_to_server = input() client.send(send_to_server.encode()) data = client.recv(1024) print(data.decode()) if data.decode()==‘exit‘: break client.close()
以上代码只能实现一个客户端和服务器通信。要实现多个客户端和服务器通信,就需要使用线程。把每个客户端和服务器的连接都当做是一个线程,这样,线程之间互不干扰,顺利运行。
import socket import threading server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((‘0.0.0.0‘,8002)) server.listen() print(‘server 已经启动,欢迎连接‘) def handle_client(sock): #定义函数,线程执行体 while True: #每一个线程和服务器的通信都是多次 data = sock.recv(1024) print(data.decode()) send_to_client = input() sock.send(send_to_client.encode()) while True: #服务器不知道客户端连接的数量,所以依然使用循环 sock,addr=server.accept() #服务器连接到了一个客户端 threading.Thread(target=handle_client,args=(sock,)).start() #启动一个线程执行和客户端的交互
在使用线程实现了多个客户端和服务器之间的通信后。
要实现群聊的功能,就把服务器当做一个转发机构,专门转发各种客户端发来的信息。
由于在客户端中input方法输入发送数据,而该方法是一个阻塞方法,必须先输入再发送。所以也可把客户端的接收,发送看做是一种线程,发送接收互不干扰。
在群聊中,设置客户端标识,方便所有客户端明确信息从哪里发出。
关闭某个客户端后,服务器不会报错,需要异常处理机制。
import socket import threading server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((‘0.0.0.0‘,8004)) server.listen() print(‘server 已经启动,欢迎连接‘) client_sockets = [] def handle_client(sock): #服务器转发数据,定义客户端标识,处理客户端退出异常 try: #处理某个客户端退出的异常 username=sock.recv(1024).decode() #接收客户端标识 for client in client_sockets: #发送消息说明每个客户端加入群聊 client.send((‘欢迎【‘+username+‘】加入群聊‘).encode()) while True: #接收客户端标识后,开始接收客户端消息 data=sock.recv(1024).decode() #接收客户端标识 if len(client_sockets)>0: #客户端列表中国如果有客户,向每个客户端发送消息 for client in client_sockets: client.send((username+‘说:‘+data).encode()) except Exception as e: client_socket.remove(sock) #出现客户端退出群聊,服务器出现异常,删掉该连接 for client in clietn_sockets: #向每个客户端发送某客户端退出群聊 client.send((username+‘已退出群聊‘).encode()) while True: #循环出现多个客户端连接 sock,addr= server.accept() client_sockets.append(sock) sock.send(‘欢迎加入群聊,请输入您的昵称:‘.encode()) threading.Thread(target=handle_client,args=(sock,)).start() #启动服务器连接客户端 #上述是实现群聊的完全代码 #以下是客户端代码 import socket import threading client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect((‘127.0.0.1‘,8004)) def receive(client): while True: print(client.recv(1024).decode()) def sendto(client): while True: send_to_other_client = input() client.send(send_to_other_client.encode()) threading.Thread(target=receive,args=(client,)).start() threading.Thread(target=sendto,args=(client,)).start()
在群聊的基础上,实现私聊。需要使用字典数据类型存储每个客户端的连接和输入的昵称名。
客户端的代码不需要做出改变。
import socket import threading server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((‘0.0.0.0‘,8004)) server.listen() print(‘server 已经启动,欢迎连接‘) client_sockets = {} #使用字典数据类型,存放连接和输入昵称之间的映射 def handle_client(sock): #处理私聊 try: #处理私聊,某客户端退出群聊异常不能缺失 username=sock.recv(1024).decode() #获取输入昵称 client_sockets[sock]=username #连接和输入昵称相互匹配 for client in client_sockets.keys(): client.send((‘欢迎【‘+username+‘】加入群聊‘).encode()) while True: #客户端输入循环 data=sock.recv(1024).decode() #服务器接受了客户端昵称后,再接受信息 send_data = ‘【‘+username+‘】说:‘+data if data.startswith(‘@‘): #处理私聊,私聊以@开头 msg=data.split(‘ ‘) #分割输入信息, private_name=msg[0][1:] #获取输入昵称 for k,v in client_sockets.items(): #遍历映射,查找符合的昵称 if v==private_name: #找到符合的用户昵称 k.send(send_data.encode()) #向该昵称的连接发生私聊信息 else: #不是私聊,就是普通群聊 if len(client_sockets)>0: for client in client_sockets.keys(): #依次遍历各个连接 client.send(send_data.encode()) exception Exception as e: client_sockets.pop(sock) #出现异常,删除连接 for client in client_sockets.keys(): client.send((username+‘已退出群聊‘).encode()) while True: #客户端连接未知 sock,addr=server.accept() client_sockets[sock]=‘‘ sock.send(‘欢迎您加入群聊,请输入您的昵称:‘.encode()) threading.Thread(target=handle_client,args=(sock,)).start() #启动服务器,连接客户端
相关推荐
一叶梧桐 2020-10-14
lzzyok 2020-10-10
digwtx 2020-09-14
efeve 2020-09-14
poplpsure 2020-08-17
ITxiaobaibai 2020-07-26
libowenhit 2020-07-23
luckykapok 2020-07-06
hongsheyoumo 2020-06-27
jannal 2020-06-21
lanmantech 2020-06-16
咻咻ing 2020-06-16
weibingbingnet 2020-06-14
woyanyouxin 2020-06-04
houjinkai 2020-06-03
txj 2020-06-02
Chydar 2020-05-15