欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。

作者:肖涛  Python爱好者社区专栏作者  个人公众号:GankSharer

个人网站: https://inspurer.github.io/

简书: https://www.jianshu.com/u/1b872cf08f32

这个项目的由来是来自计算机网络课程学习的大作业,基于socket套接字写一个超小型的QQ,晚上8点到12点的奋战,编码工作大致做完了,GUI框架也有了,特此分享出来。

功能介绍

已完成

支持单人聊天、支持群聊(所有的人都在一个群)

支持单人收发文件、群收发文件

多线程实现并发

人性化的UI界面

To do list

给每个ip维护一个昵称,方便聊天

支持单人收发文件、群收发文件

select实现并发

操作说明

如图所示:

左边是用户框架,右边是消息框架

选择`已登录用户`,消息/文件是群发的

选择树分支下的某个ip,消息/文件是私发给这个ip的

`消息``文件`二选一即可发送,优先发送消息

主要技术点

socket编程,实现点对点通信

消息格式统一采用json格式,统一打包和解析

wxPython打造GUI界面

多线程编程、函数式编程

主要代码

采用python环境编写,pycharm+python3.5.1环境;

下面仅给出主要代码

服务端server.py

def socketHander(connectionSocket):
    global connectionSocketList
    connectionSocketList.append(connectionSocket)
    connectionSocket.settimeout(2)
    for socket in connectionSocketList:
        socket.send(json.dumps(updateConnectionList()).encode("utf-8"))
    while True:
        try:
            # 接收消息
            receivedMessage = connectionSocket.recv(1024)
            if not receivedMessage:
                time.sleep(1)
                continue
            receivedMessage = receivedMessage.decode("utf-8")
            receivedMessage = json.loads(receivedMessage)
            print(receivedMessage)

type = receivedMessage.get("type")

if __name__ == "__main__":
    serverSocket = socket(AF_INET,SOCK_STREAM)
    serverSocket.bind((serverIp,serverPort))
    serverSocket.listen(100)
    while True:
        connectionSocket,addr = serverSocket.accept()
        print(connectionSocket.getpeername()) #('127.0.0.1', 1958)
        Thread(target=socketHander,args=(connectionSocket,)).start()

客户端client.py

def socketHander(self):
    self.clientSocket = socket(AF_INET, SOCK_STREAM)
    self.clientSocket.connect((serverIp, serverPort))
    self.clientSocket.settimeout(2)
    self.ip,self.port = self.clientSocket.getsockname()
    print("self ip",self.ip)
    while True:
        #发送消息
        if len(self.sendMessage) == 0:
            pass
        else:
            if self.isChoosedFile == True:
                self.clientSocket.send(json.dumps(self.sendMessage).encode("utf-8"))
                self.messageList.AppendText("文件[" + self.fileName + "]发送成功\r\n")
                self.fileName = None
                self.dataOfChoosedFile = None
                self.isChoosedFile = False
                self.sendMessage = ""

else:
                self.clientSocket.send(json.dumps(self.sendMessage).encode("utf-8"))
                self.messageList.AppendText("消息["+self.sendMessage.get("content")+"]发送成功\r\n")
                self.input.SetLabelText("")
                self.sendMessage = ""

try:
            # 接收消息
            receivedMessage = self.clientSocket.recv(1024)
            receivedMessage = receivedMessage.decode("utf-8")
            receivedMessage = json.loads(receivedMessage)
            print(receivedMessage)
            type = receivedMessage.get("type")

# 客户端接收服务端发来的转发消息
            if type == "1":
                print("客户端收到消息")
                sourceIp = receivedMessage.get("sourceIP")
                content = receivedMessage.get("content")
                if sourceIp == self.ip:
                    pass
                else:
                    self.messageList.AppendText("来自:["+sourceIp+"]的消息:["+content+"]\r\n")

elif type == "2":
                # 客户端接收服务端发来的刷新列表请求
                self.userList = receivedMessage.get("content")
                self.setUserList()

elif type == "3":
                filename = receivedMessage.get("filename")
                print("rrrr",filename)
                with open(filename,"w") as f:
                    f.write(receivedMessage.get("content"))
        except:
            print("等待数据...")
            pass
    pass

def setUserList(self):
    self.userListTree.DeleteChildren(self.rootID)
    for user in self.userList:
        # if user == self.ip:
        #     continue
        self.userListTree.AppendItem(self.rootID,user)
    pass

函数说明

函数名称

函数功能

socket(param1,param2)

创建一个套接字,param1指明网络层协议,常用AF_INET(ip协议);param2指明传输层协议,常用SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)

bind((param1,param2))

绑定socket到指定的ip(param1)和端口(param2),注意param1,param2必须组成一个元组

listen(param)

指明服务端最大的客户端连接数

connect((param1,param2))

客户端连接到指定的服务端,参数同bind()

accept()

无参数,服务端接收来自客户端的连接请求

关于配置两台PC的连接过程,我已经将过程纪录于此:局域网下两台PC机互联填坑之路 :https://blog.csdn.net/ygdxt/article/details/86562919

下一篇,我们将考虑将服务端部署到阿里云服务器,突破局域网的限制,随时随地聊天。

本篇博客我们把通信范围拓展到整个互联网

私有/公有ip

为什么socket绑定了ip地址和端口后,只能在局域网中通信呢,这就需要我们区分私有ip和公有ip

公有IP

公有IP地址是由INIC(Internet Network Information Center 因特网信息中心)负责。这些IP地址分配给向INIC提出申请并成功注册的组织机构。通过公有IP地址能直接访问因特网,当然公有IP是要钱的。

私有IP

随着网络的发展,为节省可分配的注册IP地址,有一组IP地址被拿出来专门用于私有IP网络,称为私有IP地址。私有IP地址范围:

A类: 10.0.0.0~10.255.255.255

B类:172.16.0.0~172.31.255.255

C类:192.168.0.0~192.168.255.255      这些地址是不会被Internet分配的,它们在Internet上也不会被路由,虽然它们不能直接和Internet网连接,但通过技术手段仍旧可以和 Internet通讯(NAT技术)。公网IP是直接与英特网连接可以直接访问网络(上网),而私有IP地址则是在局域网中使用的IP地址,私有IP是不能直接上网的(无法直接和公网通信),当私有网络内的主机要与位于公网上的主机进行通讯时必须经过地址转换,将其私有地址转换为合法公网地址才能对外访问。也就是要使用NAT-Network Address Translation 网络地址转换技术。      那么平时我们的电脑是如何上网的呢?比如我们办理了电信宽带,拉一根网线连接到我们的电脑,我们的电脑就能上网了。实质上此时我们的电脑是一个私有IP,电信那边购买了一个公有IP,我们电脑和电信的公有IP之间有一个NAT技术设备,也就是说我们能上网是通过电信的公有IP实现的。      如果在家安装了路由器我们的多台电脑连接在这个路由器上,那么这些电脑直接就构成了局域网,在这几台电脑上可以直接进行局域网的通信。但是你家里构成的局域网和公司的局域网是不能通过局域网通信的。

在这里记录私有IP和公有IP的原因在于socket网络通信需要区别,以便我们知道哪些IP之间是不能通信的,哪些IP之间是可以通信的。从上述原理我们就知道同一个局域网内的设备A和设备A,设备A和设备B,广域网内的设备A和设备B可以实现双向连接通信,局域网的设备A和广域网的设备B可以单向连接(只能由局域网去连接广域网,也就是局域网是客户端,广域网是服务端;因为广域网的IP是固定且唯一的,局域网连接网络通过指定这个公有IP就能找到这台计算机,找的过程是局域网连接电信网络,通过NAT技术将这个局域网私有IP转换为公有IP然后再去和指定的公有IP通信,这样就可以找到指定的公有IP,相反私有IP是不能被公有IP找到的)通信。不同局域网之间的设备不能通信。

私有ip和公有ip参考了博客 https://blog.csdn.net/youand_me/article/details/83109238

思路分析

了解上述区别了,我们要解决的一个问题是,获得一个可自由使用公有ip,这里推荐使用阿里云服务器,下面就是整个server/client系统上云的配置过程。

阿里云服务器配置

购买阿里云服务器

购买界面传送门:https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=otrai1l4

选择最低配置即可满足需求,完成学生认证后服务器低至9.5元/每月,阿里爸爸算是比较良心了哈哈  如果你不愿花钱,可以联系我免费使用我的阿里云服务器。前提是我的服务器没有到期。

这里有系统镜像和应用镜像,我的理解是应用镜像是在系统镜像上预装了一些应用软件,这里我选择的是系统镜像、Ubuntu 16.04 64位系统,其实这些配置在购买完成后是可以修改的,相等于重装系统。  由于是Linux系统,需要掌握一些基本的linux终端命令,这个很简单,百度十分钟就学会了。

云服务器配置

概览处修改密码

防火墙处设置规则

服务器默认只开放了指定端口,如果想要通过更多端口来访问服务器,我们需要添加一个规则,下图中最后一个规则就是我添加的

云服务器环境搭建

点击页面右上角的远程连接,可打开一个远程连接终端,我们就是这样来控制服务器的,玩过linux系统的同学应该很熟悉。

输入sudo su root切换至root身份

虽然报了个错,但是也切换到root了,暂且忽略这个错误,注意最好不要使用屏幕提示的那样升级Ubuntu至18.04.

由于我们的是用python编码的,所以需要python环境,而ubuntu是预装了python的,不过是python2.7,我们可以通过python -V来查看python版本,所以下一步我们要做的就是安装python3,注意一定一定不要卸载python2,否则系统会非常脆弱。

安装

wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz

解压安装包

tar zxvf Python-3.6.3.tgz

切换到解压目录

cd Python-3.6.3

安装配置,同时指定安装路径

./configure --prefix=/usr/local/python36

编译

make

安装

make install

到此为止python3安装完毕,此时输入python -V,不出意外依然是输出python2.7,还需要一步修改python3为默认才行,这个过程叫做软连接

软连接

mv /usr/bin/python /usr/bin/python.bak

ln -s /usr/local/python36/bin/python3.6 /usr/bin/python

到此python3的环境算是完全配置好了。

上传python代码

下一步就是要把我们的代码上传到阿里云服务器了,为了以后方便,先在云服务器上新建一个myfile文件夹,命令是:

mkdir myfile

然后windwos下连接linux服务器还需要下载一个软件,putty,非常小巧,也非常强大、好用

putty传送门:

https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

下载好之后安装,除了修改安装路径其余都是一直next,最后finish。

在“运行”中输入cmd,打开控制台,切换到刚才Putty的安装目录下,我的是d:\putty,然后输入pscp命令,我们需要这个命令来实现文件的上传。如下图所示,命令格式为:

pscp C:\Users\lenovo\Desktop\aliyun\server.py root@xx.xxx.xxx.xx:/home/admin/myfile/

即pscp 要上传的文件路径 服务器账号@服务器IP地址:要存放在服务器的位置路径,服务器账号一般固定是root

输入命令后出来这个:

,要不要在缓存中存储密码,为了安全输入n吧,回车后再输入密码,如果没出错的话,文件已经上传到服务器了,在服务器上可以通过ls命令查看

运行python代码

理论上说使用命令:

python server.py

就能运行python了,但是这样有一个缺点就是一旦把连接终端关闭,server.py运行的进程已经被杀死了。要想一天24小时使代码在后台运行,可使用命令。

nohup python server.py &

代码打印信息不再在终端输出,而是保存在了同目录下的nohup.out里。

运行结果示例

左边是云服务器,右边是本地客户端

Python的爱好者社区历史文章大合集

2018年Python爱好者社区历史文章合集(作者篇)

2018年Python爱好者社区历史文章合集(类型篇)

关注后在公众号内回复“ 课程 ”即可获取:

小编的转行入职数据科学(数据分析挖掘/机器学习方向)【最新免费】

小编的Python的入门免费视频课程

小编的Python的快速上手matplotlib可视化库!

崔老师爬虫实战案例免费学习视频。

陈老师数据分析报告扩展制作免费学习视频。

玩转大数据分析!Spark2.X + Python精华实战课程免费学习视频。

自己动手打造mini型QQ相关推荐

  1. 宏基微型计算机机箱怎么打开,机箱也智能 自己动手打造自动温控机箱

    盛夏酷暑,当自己享受着空调冷气袭面的时候,可曾想到朝夕相处的电脑正面临着天气温度与日俱增的煎熬?如何让自己的机箱拥有出色的散热性能,是每一位DIYer都需要面对的挑战.与其整日开着空调,不如自己DIY ...

  2. (转)如何动手打造属于自己的智能家居

    转自:http://www.cocoachina.com/programmer/20140629/8974.html 2014-06-29 14:11 编辑: suiling 分类:程序人生 来源:C ...

  3. 程序员如何动手打造属于自己的智能…

    自己动手打造属于自己的智能家居(一) 最近智能家居比较火,各种电子产品也层出不穷,于是利用业余时间,学了学,将自己的房子简单改造了一下,也算体验一下智能家居.在开始正文之前,有必要先声明一下: 1.我 ...

  4. 程序员如何动手打造属于自己的智能家居

    本文转自 奔跑的小乌龟 的博客 自己动手打造属于自己的智能家居(一) 最近智能家居比较火,各种电子产品也层出不穷,于是利用业余时间,学了学,将自己的房子简单改造了一下,也算体验一下智能家居.在开始正文 ...

  5. 微信是怎么打造平台型生态商业模式的?

    这两天写了两篇文章: <自营.自营+平台.平台>,讲到了三种业态,以及每种业务需要的关键要素和关键能力 <一颗大米>,最后一节部分讲到了三种业态都共同需要的核心数字化中台 今天 ...

  6. 转帖: 80分钟打造娱乐型ubuntu7.10

    原贴  http://forum.ubuntu.org.cn/viewtopic.php?t=93733&highlight= 序言 本文针对菜鸟而写,高手略过!对菜鸟来说,不要先研究里面的命 ...

  7. 硬盘安装+游戏功能+虚拟机XP-80分钟打造娱乐型ubuntu7.10[转]

    硬盘安装+游戏功能+虚拟机XP-80分钟打造娱乐型ubuntu7.10[转] 来源: ChinaUnix博客 日期: 2008.01.20 22:44 (共有0条评论) 我要评论   序言 本文针对菜 ...

  8. tp3 普通模式url模式_《终身成长》:三个步骤打造成长型思维模式,普通人也可以成功...

    罗伯特很小是一个聪明的孩子,父母以他为傲,经常夸奖他,对他表达爱.结果他没有考上一个纽约第1名的幼儿园,父母就不像以前那样对他了,不会再经常表达爱,夸奖他,对他就越来越冷淡,他在父母眼里是一个失败者, ...

  9. 7 centos 查看程序文件数量_「动手打造家庭媒体网络平台」安装篇-centos搭建DLNA媒体服务...

    大家好,我是路程lucky,热爱开发.设计.学习.生活.爱捣鼓的web前后端工程师~ 本文的重点是在之前文章提到创建的centos基础上继续搭建DLNA媒体服务.由于centos的系统是从零开始初步安 ...

  10. 深入浅出PE文件格式---自己动手打造PE Show

    深入浅出PE文件格式---自己动手打造PE Show                                                             作者:WiNrOOt // ...

最新文章

  1. .net 开源组件推荐 之 StackExchange
  2. C语言笔记系列文章 索引目录表(持续更新中......)
  3. Canal全方位深入讲解,看这一篇就够了
  4. linux校园网电脑开wifi密码,Linux/Ubuntu 16.04 使用校园网客户端Dr.com DrClient 有线连网,同时开启WiFi热点...
  5. http协议报文体_Java面试中可能涉及到的通信协议类问题
  6. 译 | .NET Core 3.0 对诊断的改进
  7. Windows平台下安装证书文件cer的步骤
  8. 【转】beyond compare 启动提示“应用程序发生错误”
  9. 一些值得学习的Unity教程 (很实用的包括源码)
  10. python 拼音输入法_隐马尔科夫模型python实现简单拼音输入法
  11. linux 下查看硬件信息(mac,IP地址,硬盘型号,序列号等)
  12. 多账号统一登陆,账号模块的系统设计
  13. OpenLayers之多源数据加载七:矢量地图
  14. 计算机系统运用的科学原理,人工智能的工作原理是什么?
  15. C/C++刁钻问题各个击破之细说sizeof .
  16. 微信服务商平台ApiV3接口
  17. Linux运维,到底如何入门?常用linux操作指令盘点!
  18. Centos7系统下部署Gitlab+Jenkins+Docker 实现自动化部署项目
  19. 为什么我对流程情有独钟?
  20. 专业学位计算机技术排名,山东师范大学计算机技术(专业学位)专业考研难度分析-专业排名-难度大小...

热门文章

  1. miniprogram-ci官方文档
  2. CentOS系统下各文件夹的作用
  3. p17.matplotlib:图中图
  4. Flask 物联网局部应用情景
  5. 服务器证书类型有哪些
  6. mysql long varchar2_long类型字段转换成varchar2类型
  7. asp.net将图片变成圆形
  8. python自学视频下载_Python下载哔哩哔哩学习视频
  9. matlab代码 布谷鸟优化算法CS原代码, 包含23个基准测试函数,都可运行
  10. 多域名HTTPS 证书