300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > socket多线程图形化界面聊天室实例

socket多线程图形化界面聊天室实例

时间:2022-06-27 22:06:39

相关推荐

socket多线程图形化界面聊天室实例

sockert多线程聊天室

一、项目地址二、socket简介三、socket类型1、流格式套接字(SOCK_STREAM)2、数据报格式套接字(SOCK_DGRAM)四、socket通信逻辑五、socket创建六、socket编程完整步骤(TCP)1、服务端2、客户端七、socket(TCP)多线程图形化界面聊天室实例1、需求分析2、具体实现(1)服务器端(2)客户端八、远程服务器测试

效果图

一、项目地址

socket-chat-room

二、socket简介

socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

socket “插座”

socket 的典型应用就是 Web 服务器和浏览器:浏览器获取用户输入的 URL,向服务器发起请求,服务器分析接收到的 URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,就将文字、图片、视频等元素呈现给用户。

三、socket类型

根据数据的传输方式,可以将 Internet 套接字分成两种类型。通过 socket() 函数创建连接时,必须告诉它使用哪种数据传输方式。

1、流格式套接字(SOCK_STREAM)

流格式套接字(Stream Sockets)也叫“面向连接的套接字”,在代码中使用SOCK_STREAM 表示。

特点:

用TCP协议;数据在传输过程中不会消失;数据是按照顺序传输的;数据的发送和接收不是同步的。

可以将 SOCK_STREAM 比喻成一条传送带,只要传送带本身没有问题(不会断网),就能保证数据不丢失;同时,较晚传送的数据不会先到达,较早传送的数据不会晚到达,这就保证了数据是按照顺序传递的。

2、数据报格式套接字(SOCK_DGRAM)

数据报格式套接字(Datagram Sockets也叫“无连接的套接字”,代码中使用SOCK_DGRAM 表示。

特点

用UDP协议;强调快速传输而非传输顺序;传输的数据可能丢失也可能损毁;限制每次传输的数据大小;数据的发送和接收是同步的。

众所周知,速度是快递行业的生命。用摩托车发往同一地点的两件包裹无需保证顺序,只要以最快的速度交给客户就行。这种方式存在损坏或丢失的风险,而且包裹大小有一定限制。因此,想要传递大量包裹,就得分配发送。

QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 来传输数据,因为首先要保证通信的效率,尽量减小延迟,而数据的正确性是次要的,即使丢失很小的一部分数据,视频和音频也可以正常解析,最多出现噪点或杂音,不会对通信质量有实质的影响。

注意:SOCK_DGRAM 没有想象中的糟糕,不会频繁的丢失数据,数据错误只是小概率事件。

四、socket通信逻辑

socket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个文件,一个服务端,一个客户端。

其通信逻辑如下(图源网络):

五、socket创建

此处以Python语言为例,说明如何创建套接字。

在Python中,import socket后,用socket.socket()方法来创建套接字,语法格式如下:

sk = socket.socket([family[, type[, proto]]])

参数说明:

family: 套接字家族,可以使AF_UNIX或者AF_INET。

type: 套接字类型,根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM,也就是TCP和UDP的区别。

protocol: 一般不填默认为0。

下面是具体的参数定义:

通过sk = socket.socket()方法,我们可以获得一个socket对象sk,也就是通常说的获取了一个“套接字”,该对象具有以下方法:

注意事项

Python3以后,socket传递的都是bytes类型的数据,字符串需要先转换一下,string.encode()即可;另一端接收到的bytes数据想转换成字符串,只要bytes.decode()一下就可以。

在正常通信时,accept()和recv()方法都是阻塞的。所谓的阻塞,指的是程序会暂停在那,一直等到有数据过来。

六、socket编程完整步骤(TCP)

1、服务端

创建套接字,绑定套接字到本地IP与端口:

socket.socket(socket.AF_INET,socket.SOCK_STREAM),

设置socket选项(可选),s.bind() 开始监听连接:s.listen()

进入循环,不断接受客户端的连接请求:s.accept() 接收传来的数据,或者发送数据给对方:s.recv()

s.sendall() 传输完毕后,关闭套接字:s.close()

2、客户端

创建套接字,连接服务器地址:socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect()连接后发送数据和接收数据:s.sendall(),s.recv()传输完毕后,关闭套接字:s.close()

七、socket(TCP)多线程图形化界面聊天室实例

1、需求分析

通过以上对socket编程的一些讲解,可以发现单纯的在命令行实现socket通信并不算太难,如果给它加上图形化界面,会更直观。所以我们就一起来实现一个socket(TCP)多线程图形化界面聊天室吧。

根据需求分析,此聊天室项目主要包含两个方面:

socket网络编程图形化界面

socket网络编程我们上面已经讲解过一些基础知识,接下来只要用Python去实现即可,。至于图形化界面,我们这里用的是python自带的GUI库tkinter,其跨平台性能良好,并且本身就是为快速GUI开发而生,已经比较成熟。除了tkinter,读者也可以使用其他的GUI框架,比如PyQt,此处就不具体实现了。

2、具体实现

我们结合代码具体讲解,此处主要包含两个py文件,一个服务器端server.py,一个客户端client.py。因为服务器端主要是接受客户端请求并返回消息,所以此处我们将图形化界面的编写融合到客户端的代码文件中,更加“直观”的感受客户端的请求发送。

需要注意的是,此处我们使用了Python内置的threading模块进行多线程处理,因为Python的socket模块,默认情况下创建的是单进程单线程,同时只能处理一个连接请求。

(1)服务器端

服务端主要包含用户字典库,以及服务端接受及处理服务端请求。

此处为类的定义(完整代码见:socket-chat-room):

import socket import threadingfrom settings import Local_Host,Local_Port#User database for authenticationdb = {'北落':'Love','师门':'You','北落师门':'Forever',} class ChatServer:clients_list = []#客户端列表last_received_message = "" #接收的最新请求def __init__(self):self.server_socket = Noneself.create_listening_ser

运行服务器端server.py,可以发现服务正在监听等待请求消息:

(2)客户端

客户端主要为图形化界面的实现,以及请求的发送与接收。

此处为类的定义(完整代码见:socket-chat-room)

from tkinter import Tk, Frame, Scrollbar, Label, END, Entry, Text, VERTICAL, Button, messagebox import socket import threading class GUI:client_socket = Nonelast_received_message = None def __init__(self, master):self.root = masterself.chat_transcript_area = Noneself.name_widget = Noneself.password_widget = Noneself.enter_text_widget = Noneself.join_button = Noneself.initialize_socket() #初始化socketself.initialize_gui() #图形化界面self.listen_for_incoming_messages_in_a_thread() #监听消息

运行客户端代码client.py),可以看到服务端显示有客户端请求:

此时客户端部分,桌面会弹出一个新的页面,如下所示:

可以看到,图形化界面主要包含三个部分:

聊天区:用于展示(多个)客户端发送的请求消息用户信息区:用户的昵称、密码,点击加入群聊,服务端进行身份验证,通过后,可以开始聊天。消息编写发送区:键入需要发送的消息,回车发送。

键入昵称与密码后,服务端会进行身份验证,主要是通过将昵称与密码结合成字符串,发送至服务端,服务端将其与自身保存的用户字典中的用户进行匹配。若在字典中,则验证通过,服务器端显示成功连接:

此时客户端的昵称、密码输入框以及加入群聊按钮都被禁用,即不允许再修改身份:

若身份验证失败,则服务端显示身份验证失败,断开连接:

此时客户端弹出身份验证失败提示框:

当新的客户端加入聊天室时,聊天区会展示该用户已加入群聊(has joined)。在两个客户端分别键入消息并发送,其结果如下:

注意:

通过tkinter的事件绑定,昵称、密码输入后,点击“加入群聊”按钮,输入框状态修改为"disabled",即无法再修改身份信息。

聊天区也绑定了事件,即聊天区消息无法通过键盘输入或修改。

聊天区无法修改历史聊天消息。

当未输入昵称或密码,直接点击“加入群聊按钮”,或者尝试在消息区编写发送消息,系统会弹出提示框,提醒用户先进行登录。

八、远程服务器测试

上面的聊天室实现是基于本机的,服务端与客户端绑定的都为本机ip:127.0.0.1,端口port:10319。那么如何进行远程服务器测试呢?

重要的一点是要将用于socket通信的远程服务器的端口打开,注意是出方向入方向同时打开(笔者此处使用4004端口)。

服务器端口设置

并且需要将远程服务器ip绑定为"0.0.0.0",即允许监听所有端口。

设置后,客户端与服务端即可正常通信,亲测可用!

Reference

[1] /course/python/76

[2]/cpp/socket/

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。