Python实现网络多人聊天室 - Windows
项目名称:多人聊天室
项目结构:
client.py
server.py
settings.py
项目思路:服务端接收客户端连接,客户端发送信息给服务端,服务端将信息发送给所有客户端。
项目实现:主进程负责接收键盘输入(sys.stdin.readline),使用multiprocessing.Process函数创造一个进程,在这个进程中,使用select监听两个套接字,一个套接字负责服务端与客户端之间的消息接收与发送,另一个负责与主进程保持联系。
- # settings.py
- import os
- from socket import *
- from random import randint
- import shelve
- HOST = "127.0.0.1"
- # 服务端和客户端的连接地址
- SOCK_PORT = 4444
- SOCK_ADDR = HOST, SOCK_PORT
- # 服务端server.py文件中供pipe_server和pipe_client使用的套接字地址
- SER_PIPE_PORT = 4321
- SER_PIPE_ADDR = HOST, SER_PIPE_PORT
- # 客户端client.py文件中供pipe_server和pipe_client使用的套接字地址
- # 因为每个客户端都必须有不同的套接字来作起到连接键盘输入和网络套接字之间的管道的作用
- # 使用一个文件记录下每一次运行出现的端口号,以保证不重复
- if not os.path.exists("ports.dat"):
- f = shelve.open("ports")
- f["ports"] = []
- f = shelve.open("ports")
- while True:
- n = randint(4500, 10000)
- if n not in f["ports"]:
- f['ports'].append(n)
- break
- f.close()
- CLI_PIPE_PORT = n
- CLI_PIPE_ADDR = HOST, CLI_PIPE_PORT
- # 缓冲区大小
- BUFFERSIZE = 1024
- # 返回一个TCP服务端套接字
- def server(addr):
- sock = socket(AF_INET, SOCK_STREAM, 0)
- sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
- sock.bind(addr)
- sock.listen(10)
- return sock
- # 返回一个TCP客户端套接字
- def client(addr):
- sock = socket(AF_INET, SOCK_STREAM, 0)
- sock.connect(addr)
- return sock
settings.py
- # server.py
- import sys
- import shelve
- from socket import *
- from select import select
- from multiprocessing import Process
- from settings import *
- def listen(sock_server, pipe_server):
- # IO多路复用:循环监听套接字
- rlist = [sock_server, pipe_server]
- wlist = []
- xlist = []
- print("等待连接...")
- while True:
- rs, ws, xs = select(rlist, wlist, xlist)
- for r in rs:
- if r is sock_server:
- # 接受客户端连接
- conn, addr = sock_server.accept()
- rlist.append(conn)
- elif r is pipe_server:
- # 接收键盘输入并发送到所有客户端去
- conn, addr = pipe_server.accept()
- data = conn.recv(BUFFERSIZE)
- data = bytes("管理员:", "UTF-8") + data
- for c in rlist[2:]:
- c.send(data)
- conn.close()
- else:
- # 接收客户端信息
- # 将客户端信息发送到所有的客户端中去
- try:
- data = r.recv(BUFFERSIZE)
- except:
- r.close()
- rlist.remove(r)
- else:
- print(data.decode(), end="")
- for c in rlist[2:]:
- c.send(data)
- def clear_all():
- f = shelve.open("ports")
- f['ports'].clear()
- f.close()
- if __name__ == '__main__':
- # 首先将ports内容都删除
- clear_all()
- # 创建两个套接字
- # 套接字sock_server是一个TCP服务端,负责服务端与客户端的交流
- # 套接字pipe_server也是一个TCP服务端,不过起到管道的作用,负责接收键盘输入
- sock_server = server(SOCK_ADDR)
- pipe_server = server(SER_PIPE_ADDR)
- # 开始一个子进程,执行listen函数
- p = Process(target=listen, args=(sock_server, pipe_server))
- p.daemon = True
- p.start()
- # 循环接收键盘输入
- while True:
- try:
- # 从标准输入流(键盘)读取一行
- data = sys.stdin.readline()
- except KeyboardInterrupt:
- # 如果遇到退出/中止信号,关闭套接字,结束子进程,退出程序
- sock_server.close()
- pipe_server.close()
- p.terminate()
- clear_all()
- break
- if not data:
- # 如果从键盘获取数据为空,继续循环
- continue
- else:
- # 获得键盘数据,创建客户端套接字pipe_client,将键盘输入传输给pipe_server
- pipe_client = client(SER_PIPE_ADDR)
- pipe_client.send(bytes(data, "UTF-8"))
- pipe_client.close()
server.py
- # client.py
- import sys
- from socket import *
- from select import select
- from multiprocessing import Process
- from settings import *
- def connect(sock_client, pipe_server, name):
- # IO多路复用:循环监听套接字
- rlist = [sock_client, pipe_server]
- wlist = []
- xlist = []
- while True:
- rs, ws, xs = select(rlist, wlist, xlist)
- for r in rs:
- if r is sock_client:
- # 接受服务端的信息
- data = sock_client.recv(BUFFERSIZE).decode()
- print(data, end="")
- elif r is pipe_server:
- # 接受键盘输入并发送给服务端
- conn, addr = pipe_server.accept()
- data = conn.recv(BUFFERSIZE)
- data = bytes(name + ":", "UTF-8") + data
- sock_client.send(data)
- conn.close()
- def get_name():
- return input("User name: ")
- if __name__ == '__main__':
- # 使用get_name函数获得用户名
- name = get_name()
- # 创建两个套接字
- # 套接字sock_client是一个TCP客户端,负责服务端与客户端的交流
- # 套接字pipe_server也是一个TCP服务端,不过起到管道的作用,负责接收键盘输入
- sock_client = client(SOCK_ADDR)
- sock_client.send(bytes(name + "加入了聊天室。\n", "UTF-8"))
- pipe_server = server(CLI_PIPE_ADDR)
- # 开始一个子进程,执行connect函数
- p = Process(target=connect, args=(sock_client, pipe_server, name))
- p.daemon = True
- p.start()
- # 循环接收键盘输入
- while True:
- try:
- # 从标准输入流(键盘)读取一行
- data = sys.stdin.readline()
- except KeyboardInterrupt:
- # 如果遇到退出/中止信号,发送退出信息,关闭套接字,结束子进程,退出程序
- sock_client.send(bytes(name + "退出了聊天室。\n", "UTF-8"))
- sock_client.close()
- pipe_server.close()
- p.terminate()
- break
- if not data:
- # 如果从键盘获取数据为空,继续循环
- continue
- else:
- # 获得键盘数据,创建客户端套接字pipe_client,将键盘输入传输给pipe_server
- pipe_client = client(CLI_PIPE_ADDR)
- pipe_client.send(bytes(data, "UTF-8"))
- pipe_client.close()
client.py
Python实现网络多人聊天室 - Windows的更多相关文章
- Python实现网络多人聊天室
网络多人聊天室 文件结构: chatroom ├── client.py # 客户端代码 ├── language.py # 语言文件 ├── server.py # 服务端代码 └── set ...
- Python实现网络图形化界面多人聊天室 - Windows
Python实现网络图形化界面多人聊天室 - Windows 项目名称:网络多人聊天室图形界面版本 项目思路: server.py 服务端文件,主进程中,创建图形化界面,询问地址(主机名,端口),点击 ...
- Python实现网络图形化界面多人聊天室 - Linux
网络图形化界面多人聊天室 - Linux Windows版本:https://www.cnblogs.com/noonjuan/p/12078524.html 在Python实现网络多人聊天室基础上, ...
- 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室
原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室
原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 66 网络编程(五)——TCP多线程实现多人聊天室
思路 客户端读写各一个类,可以使内部类,实现Runnable.读写类都与服务器端建立连接,一个收,一个发. 客户端实现接收和转发.多线程实现每个客户端的连接(使与各客户端的连接独立). 服务器端中创建 ...
- Apache MiNa 实现多人聊天室
Apache MiNa 实现多人聊天室 开发环境: System:Windows JavaSDK:1.6 IDE:eclipse.MyEclipse 6.6 开发依赖库: Jdk1.4+.mina-c ...
- 多人聊天室(Java)
第1部分 TCP和UDP TCP:是一种可靠地传输协议,是把消息按一个个小包传递并确认消息接收成功和正确才发送下一个包,速度相对于UDP慢,但是信息准确安全:常用于一般不要求速度和需要准确发送消息的场 ...
- 使用Go语言+Protobuf协议完成一个多人聊天室
软件环境:Goland Github地址 一.目的 之前用纯逻辑垒完了一个可登入登出的在线多人聊天室(代码仓库地址),这次学习了Protobuf协议,于是想试着更新下聊天室的版本. 主要目的是为了掌握 ...
随机推荐
- python将图片旋转,颠倒,修改尺寸
直接上代码,根据需求注释选择相应修改 from PIL import Image import os import os.path rootdir = r'G:\jianfeng\project\ru ...
- 《3D_Deep_Learning_for_Robot_Perception.pdf》
https://github.com/PrincetonVision/marvin
- CF1253E Antenna Coverage(DP)
本题难点在正确性证明. 令 \(f_i\) 表示 \([1,i]\) 被全部覆盖的最小花费.答案为 \(f_m\). 首先发现,添加一个区间 \([0,0]\) 不会影响答案.所以 \(f_i\) 的 ...
- 不用输入ssh -i命令行即可携带pem文件快速登录的方法
如果要登录的服务器只允许pem认证 每次输入ssh -i xxxx.pem 用户@ip 地址 就很烦 这里有个一劳永逸的方法: 进入到自己的用户目录,例如/home/me 把pem文件放在当前目录 ...
- [开源] FreeSql 配套工具,基于 Razor 模板实现最高兼容的生成器
FreeSql 经过半年的开发和坚持维护,在 0.6.x 版本中完成了几大重要事件: 1.按小包拆分,每个数据库实现为单独 dll: 2.实现 .net framework 4.5 支持: 3.同时支 ...
- python文件操作【目录大全】
总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...
- js 元素自动点击/执行问题
a标签对于一下两种方式是无效的: <a href="http://qq.com">QQ</a> $('.obj').click(); $('.obj').t ...
- 使用码云,GitHub进行版本控制,并通过WebHook进行自动部署
我们通常需要在 PUSH 代码到远程仓库时,线上环境会自动进行代码同步,这时候就需要用到WebHook,它会自动回调我们设定的http地址. 通过请求我们自已编写的脚本,来拉取代码,实现与远程仓库代码 ...
- pandas 学习 第6篇:DataFrame - 数据处理(长宽格式、透视表)
长宽格式的转换 宽格式是指:一列或多列作为标识变量(id_vars),其他变量作为度量变量(value_vars),直观上看,这种格式的数据比较宽,举个列子,列名是:id1.id2.var1.var2 ...
- 数据类型和特殊类型-C#
参考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1.集合set:纯粹的数据集合 2.线性结构:一对一的,数组 3.树形结构: ...