项目名称:多人聊天室
项目结构:
  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. flask之请求与响应、闪现(阅后即焚)、请求扩展(before,after)、中间件、LOCAL对象、偏函数、

    目录 1.flask请求与响应 2.闪现 3.请求扩展 4.中间件 5.LOCAL对象 6.偏函数 templates 1.flask请求与响应 from flask import Flask,req ...

  2. Go 循环 (for)

    循环类型 for: for a := 0; a < 10; a ++{ fmt.Println(a) } 在执行结束后 a == 10 while: a := 0 for a < 10{ ...

  3. Codeforces Round #594 (Div. 1) C. Queue in the Train 模拟

    C. Queue in the Train There are

  4. 向技术领先的华为说No,就是对国家的通信前景说No!

    历史已经证明了,任何一项可以加速人员.物资.能源.金钱.信息迁移的技术,都会让社会原有的生产力成倍地增长.中国在互联网.移动互联网保持令整个世界震惊的飞速发展,以BAT为首的诸多商业帝国建立,还有人们 ...

  5. [Pytorch Bug] "EOFError: Ran out of input" When using Dataloader with num_workers=x

    在Windows上使用Dataloader并设置num_workers为一个非零数字,enumerate取数据时会引发"EOFError: Ran out of input"的报错 ...

  6. python接口自动化11-pytest入门

    前言 pytest是一个非常成熟的全功能的Python测试框架,适合从简单的单元到复杂的功能测试,主要特点有以下几点: 简单灵活,容易上手: 支持参数化: 能够支持简单的单元测试: 标记测试功能与属性 ...

  7. 10-Django中间件

    中间件 Django中的中间件是一个轻量级.底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入和输出. 中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Djang ...

  8. php捕获Fatal error错误与异常处理

    php中的错误和异常是两个不同的概念. 错误:是因为脚本的问题,比如少写了分号,调用未定义的函数,除0,等一些编译语法错误. 异常:是因为业务逻辑和流程,不符合预期情况,比如验证请求参数,不通过就用 ...

  9. WPF 解决多个TreeViewItem同时触发某事件的简单方法

    原理是: 因为是双击事件,也就是同时引发了选择事件,TreeViewItem的IsSelected为True.通过触发器设置某个属性为特殊值,然后在CS页面的双击事件方法内判断是否此值即可. xaml ...

  10. java高并发系列 - 第10天:线程安全和synchronized关键字

    这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: pack ...