热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python高级编程和异步IO并发编程10_3Socket实现聊天和多用户连接

单用户连接:#coding:utf-8#server端程序importsocket#导入socket模块address(0.0.0.0,50000)#IP地址和

单用户连接:

# coding:utf-8
# server端程序
import socket # 导入socket 模块address = ('0.0.0.0', 50000) # IP地址和端口号
print('Waiting for a client now !')
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建一个空的套接字,socket.AF_INET表示创建一个IP套接字;
# socket.SOCK_STREAM表示流式socket,TCP模式;sock_DGRAM表示数据报式socket,UDP模式
server.bind(address) # 绑定(监听这个IP地址和端口的所有数据)到这个套接字上
server.listen(5) # 表示最多可以和5个客户端连接,超过5个就会拒绝
# 调用accept方法时,socket会时入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。
# accept方法返回一个含有两个元素的元组(connection,address)。
# 第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素address是客户的Internet地址
client, addr = server.accept()
data = client.recv(1000) # 指定最大可以接受消息长度为1000字节
print("Client:", client, "Said", data) # 输出client客户端信息以及接收到的数据data
client.sendall('hello'.encode("utf8")) # 发送数据
client.close() # 关闭
server.close()

# coding:utf-8
# client端程序
import socket # 导入 socket 模块try:address = ('127.0.0.1', 50000)client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(address) # 与指定地址建立连接print("Connection succeeded!")client.sendall('Hi!'.encode("utf8")) # 发送数据data = client.recv(1000)print("Server reply", data.decode("utf8"))client.close()
except:print("Connection failed.")

聊天程序

Server.py

# 聊天程序
import socket
# socket Sever,首先做了绑定,在server上不停的监听,当监听到有一个新生成的连接,就绑定一个socket,因此后续的发送是socket,而不是server
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('0.0.0.0',9999)) # bind必须绑定tuple。 如果绑定127.0.0.1,会导致通过局域网的ip无法访问
print('Waiting for a client now !')
server.listen(5)
sock,addr = server.accept() # 全局的接收,只能接收一次请求,接受以后,双方做数据交流,server用来监听,socket用于用户连通while True: # 接受后,不可以closedata = sock.recv(1024) # 一次获取1KB数据print(data.decode("utf8"))re_data = input() # 通过手工输入来做交互sock.send(re_data.encode("utf8"))

Client.py

import socket
# 初始化的client就是我们一直要用到的client,因此只需要一个client即可
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",9999)) # 连接本地服务器
print("Connection succeeded!")
while True: # 接受后,不可以closere_data = input() # 通过手工输入来做交互client.send(re_data.encode("utf8"))data = client.recv(1024) # 由发起端先发送数据过去,从client端请求数据。 而服务器端是先recv数据print(data.decode("utf8")) # 打印放在recv之后

多用户聊天

Server.py

# 聊天程序
import socket
import threading
# socket Sever,首先做了绑定,在server上不停的监听,当监听到有一个新生成的连接,就绑定一个socket,因此后续的发送是socket,而不是server
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('0.0.0.0',9999)) # bind必须绑定tuple。 如果绑定127.0.0.1,会导致通过局域网的ip无法访问
print('Waiting for a client now !')
server.listen(5)
# sock,addr = server.accept() # 全局的接收,只能接收一次请求,接受以后,双方做数据交流,server用来监听,socket用于用户连通
# 目前,一次只能连接一个client,如何实现多用户聊天,同时接入server? 就需要用到多线程,在线程里面进行循环。主线程不停的接收其它请求def handle_sock(sock,addr):while True: # 接受后,不可以closedata = sock.recv(1024) # 由发起端先发送数据过去,从client端请求数据。 而服务器端是先recv数据print(data.decode("utf8")) # 打印放在recv之后re_data = input() # 通过手工输入来做交互sock.send(re_data.encode("utf8"))while True: # 接受后,不可以closesock,addr = server.accept() # 接收到新请求时,立即交给线程,由线程进行处理新的socket。# 用线程去处理新接收的连接(用户)client_thread = threading.Thread(target=handle_sock,args=(sock,addr)) # target传递的一定是函数的名称,而不是函数的调用client_thread.start() # 启动线程

Client-x.py

# client-n.py
import socket
# 初始化的client就是我们一直要用到的client,因此只需要一个client即可
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",9999)) # 连接本地服务器
print("Connection succeeded!")
while True: # 接受后,不可以closere_data = input() # 通过手工输入来做交互client.send(re_data.encode("utf8"))data = client.recv(1024) # 由发起端先发送数据过去,从client端请求数据。 而服务器端是先recv数据print(data.decode("utf8")) # 打印放在recv之后

先运行Server.py, 提示“Waiting for a client now !"

运行Client-1.py, 提示Connection  succeeded!

在Client-1端,输入“Client-1”, 查看Server 端,发现Server端已经收到“Client-1”

在Server端,输入“Server-1”,查看Client端,发现Client端收到了“Server-1”

 

再运行Client-2.py,提示Connection succeed!

在Client-2端,输入“Client-2”, 查看Server 端,发现Server端已经收到“Client-2”

在Server端,输入“Server-2”,查看Client-2端,发现Client端收到了“Server-2”;查看Client-1端,发现Client端没有收到“Server-2”

 

 

 

 


推荐阅读
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
author-avatar
劲朋_511
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有