项目名称:多人聊天室
项目结构:
  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的更多相关文章

  1. Python实现网络多人聊天室

    网络多人聊天室 文件结构: chatroom ├── client.py  # 客户端代码 ├── language.py  # 语言文件 ├── server.py  # 服务端代码 └── set ...

  2. Python实现网络图形化界面多人聊天室 - Windows

    Python实现网络图形化界面多人聊天室 - Windows 项目名称:网络多人聊天室图形界面版本 项目思路: server.py 服务端文件,主进程中,创建图形化界面,询问地址(主机名,端口),点击 ...

  3. Python实现网络图形化界面多人聊天室 - Linux

    网络图形化界面多人聊天室 - Linux Windows版本:https://www.cnblogs.com/noonjuan/p/12078524.html 在Python实现网络多人聊天室基础上, ...

  4. 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室

    原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  5. 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室

    原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...

  6. 66 网络编程(五)——TCP多线程实现多人聊天室

    思路 客户端读写各一个类,可以使内部类,实现Runnable.读写类都与服务器端建立连接,一个收,一个发. 客户端实现接收和转发.多线程实现每个客户端的连接(使与各客户端的连接独立). 服务器端中创建 ...

  7. Apache MiNa 实现多人聊天室

    Apache MiNa 实现多人聊天室 开发环境: System:Windows JavaSDK:1.6 IDE:eclipse.MyEclipse 6.6 开发依赖库: Jdk1.4+.mina-c ...

  8. 多人聊天室(Java)

    第1部分 TCP和UDP TCP:是一种可靠地传输协议,是把消息按一个个小包传递并确认消息接收成功和正确才发送下一个包,速度相对于UDP慢,但是信息准确安全:常用于一般不要求速度和需要准确发送消息的场 ...

  9. 使用Go语言+Protobuf协议完成一个多人聊天室

    软件环境:Goland Github地址 一.目的 之前用纯逻辑垒完了一个可登入登出的在线多人聊天室(代码仓库地址),这次学习了Protobuf协议,于是想试着更新下聊天室的版本. 主要目的是为了掌握 ...

随机推荐

  1. linux shell攻略学习笔记二

    1.Cat命令 这么多命令,常用的 Cat –n file  显示文件以及行数 Cat - echo 'Text through stdin' | cat - file.txt Text throug ...

  2. python做中学(三)条件编译的用法

    C代码中经常使用条件编译,python中该怎么用呢?Python没有像C或C或Java甚至Java一样编译,python文件被“即时”编译,您可以将其视为类似于Basic或Perl的解释语言 只需使用 ...

  3. js函数只执行一次,函数重写,变量控制与闭包三种做法

    一.情景需求 调用后台接口需要附带token信息,那么在每个请求的头部添加token的做法就不太优雅了:一个网站请求100次,那就得写添加100次token,假设某天接口有所变动,改起来就十分麻烦了. ...

  4. 1+x证书Web前端开发HTML+CSS专项练习测试题(八)

    1+x证书Web前端开发HTML+CSS专项练习测试题(八) 官方QQ群 1+x 证书 Web 前端开发 HTML+CSS 专项练习测试题(八) http://blog.zh66.club/index ...

  5. LeetCode | 机器人能否返回原点

    放假的时间已经过去一半了,每天坚持看一个多小时的书,时间虽然不多,但是能专心把书看进去就可以了.今天分享的是 LeetCode 上面的第 657 题,题目是<机器人能否返回原点>,这也是一 ...

  6. centos7之firewalld防火墙的配置与使用

    firewalld是centos7开始提供的管理防火墙工具,提供了一个动态管理的防火墙,当然低层仍然调用的是 netfilter . 一.区域(zone)firewalld将网卡对应到不同的区域(zo ...

  7. pandas 学习 第3篇:Series - 数据处理(应用、分组、滚动、扩展、指数加权移动平均)

    序列内置一些函数,用于循环对序列的元素执行操作. 一,应用和转换函数 应用apply 对序列的各个元素应用函数: Series.apply(self, func, convert_dtype=True ...

  8. MySQL EXPLAIN 语句

    对于 MySQL 在执行时来说,EXPLAIN 功能上与 DESCRIBE 一样.实际运用中,后者多用来获取表的信息,而前者多用于展示 MySQL 会如何执行 SQL 语句(Obtaining Exe ...

  9. 用python执行Linux命令

    例1:在python中包装ls命令 #!/usr/bin/env python #python wapper for the ls command import subprocess subproce ...

  10. python基础(27):类成员的修饰符、类的特殊成员

    1. 类成员的修饰符 类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的定义不同:私 ...