是否担心微信的数据流会被监视?是否担心你和ta聊天的小秘密会被保存到某个数据里?没关系,现在我们可以用Python做一个只属于你和ta的聊天渠道,来解除你们心中的担忧。

1.原理简介

在我们今天的教程中,将用到即时通讯的概念,即时通讯允许两人或多人同时使用网络传递文字信息、文字、语音等。即时通讯一般都基于socket连接,socket连接可用于发送或接受数据,一般的组合形式是IP+端口号

也就是说,在我们的例子中,聊天的双方,由一方要承担“服务器 ” 的责任,维持一个socket服务器,等待连接进入;另一方则是“客户端”,在服务器端维持等待状态时即可发送请求,建立连接。

当你和ta想进入“小黑屋 ” 里聊天的时候,只有有一方充当服务器,另一方充当客户端即可,作为“服务器端 ” 的那个人,在微信中将IP和端口号告诉对方,即可构建连接,在小黑屋里聊天,这个小黑屋里的数据不会被任何数据保留(除非你自己做了一个保存的数据)。

2.代码编写

好了,基本原理我们已经讲清楚了。不过,在开始教程之前,你得先安装好了Python,如果还没有安装,可以看这篇文章:https://pythondict.com/python-tutorials/how-to-install-python/

2.1 服务器端

聊天的时候,我们有时候会遇到双方同时发消息的情况。这种聊天方式就叫全双工聊天方式:“服务器”可向“客户端”发送消息,“客户端”也可向“服务端”发送消息,而且允许同时发送消息。

服务器端怎么实现全双工的聊天方式呢?其实很简单,只要用多线程就行了,主线程用于接收客户端的连接,连接成功后新建两个线程:一个用于发送消息,一个用于接收消息:

首先,建立socket服务器:

import socket
import traceback
# 设定ip和端口号
host = ''
port = 51423 
# 建立socket服务器
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen() 
while True:
    # 等待连接
    try:
        clientsock, clientaddr = s.accept()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()
        continue 

其中,AF_INET指的是用IPv4进行通信,而SOCK_STREAM指的是TCP协议。端口号你可以随意设定,服务器端的IP地址默认为空即可。

在while循环中不断等待用户的连接。如果有用户连接成功了,我们将进入下一步,分别建立发送和接受线程:

# 建立接收线程
t = _thread.start_new_thread(processRecv, (clientsock,))

# 建立发送线程
r = _thread.start_new_thread(processSend, (clientsock,)) 

clientsock就是我们得到的socket连接,processRecv和processSend分别用于处理接受信息和处理发送信息:

import _thread 
def processRecv(clientsock):
    """
    接受消息
        :param clientsock: 客户端的socket连接
    """
    while True:
        data = clientsock.recv(4096)
        if not len(data):
            break
        print (data.decode('utf-8'))
    clientsock.close()

def processSend(clientsock):
    """
    发送消息
        :param clientsock: 客户端的socket连接
    """
    while True:
        data = input("> ")
        data = data
        clientsock.sendall(data.encode('utf-8'))
    clientsock.close() 

有个小细节要注意,socket连接的sendall函数只支持bytes类型的数据,所以我们要encode(‘utf-8’)。

服务端的所有代码就这样,没错,就是这么简单。

2.2 客户端

客户端则更简单,主线程本身设定为接受消息,那么我们只需要多一个线程用于发送消息即可。客户端的全部代码如下:

#-*-coding:utf-8-*-

import _thread
import sys
from socket import *

def send_message(tcpCliSock):
    """
    发送信息
        :param tcpCliSock: 与服务端的socket连接
    """
    while True:
        message = input('> ')
        if not message:
            break
        tcpCliSock.send(message.encode('utf-8'))

    tcpCliSock.close()

if(len(sys.argv) < 3):
    HOST = 'localhost'
    PORT = 51423
else:
    HOST = sys.argv[1]
    PORT = int(sys.argv[2])

BUFSIZ = 1024
ADDR = (HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)

# 建立发送消息的线程
s = _thread.start_new_thread(send_message, (tcpCliSock,))

while True:
    rdata = tcpCliSock.recv(BUFSIZ)
    if not rdata:
        break
    print (rdata.decode('utf-8'))
    
tcpCliSock.close() 

其中,HOST部分填写对方的IP,PORT部分填写端口号。sys.argv用于通过参数输入这两个值,比如我们将客户端文件命名为:client.py, 在cmd中输入:

python client.py 127.0.0.1 51423

能直接传入参数执行脚本,除此之外,其他部分和服务端其实差不多。注意把接受到的数据decode一下(因为我们发的时候encode了)。

3. 改进

实际上,这份代码虽然可以用,但是还是存在许多问题的。比如在你们聊天的时候,突然又有一个人向服务端发送连接请求怎么办?这时候我们需要在服务端加一份拥有验证的代码,要求对方输入聊天室密码后才可建立连接。

这个密码必须是你们双方才知道的密码,任何通过第三方工具传播密码的行为都是不可靠和不安全的。这样才可以防止第三者的偷听。增加一个密码功能其实也不难,这部分交给大家自己去实现啦!

本文完整源代码下载请在公众号后台回复:聊天渠道

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python实用宝典
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。