上一节在服务器上搭建起了静态网页展示,这一节先把网页放在边,用Python处理一下终端向服务器发送数据时使用的TCP服务,在接收的同时把数据存入数据库
一、Python socket套接字完成TCP服务
1.终端部分
import socket # 导入socket库
# 新建socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('xx.xx.xxx.xx', 9999))
# 接收消息:
print(s.recv(1024).decode('utf-8'))
# 发送数据:
data = b'Ben'
s.send(data)
# 接收消息
print(s.recv(1024).decode('utf-8'))
# 结束发送
s.send(b'exit')
s.close()
如果需要具体使用的话,需要调整的是:
建立连接时的目标IP地址(注意:此处的IP地址是服务器的外网地址)和端口号(使用的端口需要在服务器安全组和防火墙放行)
以及连接上之后的操作:这里首先接收了服务器发送的内容并输出,接下来以字节类型发送字符串数据,发送完毕后接收服务器反馈,最后发出断开提示,停止socket。
2.服务器部分
1)Python文件
import socket # 导入socket库
import threading # 导入多线程库
import time # 导入暂停时间库
# 创建Socket(基于IPv4和TCP协议)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定监听端口:
s.bind(('xx.x.xx.xx', 9999))
s.listen(5) # 监听,传入等待连接的最大数量,超过的连接需要等待
print('Waiting for connection...') # 准备就绪
# 建立线程函数
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!') # 向终端发送数据
while True:
data = sock.recv(1024) # 接收终端发送的数据
time.sleep(1) # 等待接收完成
if not data or data.decode('utf-8') == 'exit':
""" 约定退出命令 """
break
sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' % addr)
# 开始监听
while True:
# 接受一个新连接
sock, addr = s.accept()
# 创建新线程来处理TCP连接
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
注意:实际使用需要修改监听的IP(服务器的内网IP,因为服务器监听的网卡搭载在内网IP上),端口号需要与终端一致。
将修改好后的Python文件通过WinSCP(上一节介绍过使用方法)上传至服务器的一个自定的文件夹。
2)控制台安全组和防火墙放行所用端口
进入腾讯云服务器控制台,先开通防火墙。
点击添加规则,选择自定义,填入端口号即可。(可以对来源IP进行限制以增加安全性,如果想要多个终端连接的话需要对所有源开放端口)。
下面在安全组中开通使用的端口。选择最上方的云产品,找到私有网络。
左侧导航栏进入安全>安全组,点击新建,可以看到有默认放通部分端口,也可以一键放通全部端口(后者存在安全隐患,真实使用不建议全部放通)。这里为了调试方便,全部放通。
3)验证终端与服务器的TCP连接
首先使用ssh远程登录服务器,使用cd命令进入刚刚写好的服务器端文件的目录下,输入:
python server1.py
运行程序,如果出现如下提示说明运行成功,程序开始监听端口: 此时服务器端的TCP服务已经启动,现在我们在本地电脑运行终端的Python代码(可以用cmd运行,也可以在配置好的VSCode上运行)。不出所料第一行会输出服务器发送的消息,第二行输出服务器接收到的信息。
而服务器也会显示连接信息和断开信息,但此时断开的仅仅时终端,服务器仍在运行,可以继续接收终端发送的数据。(想要中止程序运行可以使用快捷键Ctrl+C)
至此实现了终端与服务器双向通讯的功能,但是目前数据仅仅储存在Python程序的变量中,如果需要保存的话还需要将数据输出至本地文件。
下一步我们在服务器上安装MySQL数据库,同时和Python程序连接,让程序在收到数据之后直接储存至服务器数据库中。
二、Linux 安装 MySQL
1.安装MySQL
输入命令,之后输入y来确认安装MySQL服务端:
apt-get install mysql-server
之后等待安装:
正常情况下安装的时候会提示输入密码,但是我这一次没有提示,先忽略掉这个。输入:
netstat -tap | grep mysql
来检查SQL的状态,显示LISTEN表示端口正在监听中,数据库运行正常。接下来输入:
service mysql status
检查数据库的运行状态,出现绿色灯表示一切正常。下面输入:
mysql -u root -p
使用root用户登录,直接回车跳过输入密码。使用SQL语言(注意一定要在结尾带上“;”):
show databases;
来显示现有的数据库:
至此数据库安装成功,下一步使用SQL语言创建数据库和表单。
2.新建数据库和表单来储存接收到的数据
数据库和表单的创建也可以通过Python来实现,但是这里将每次接收到的数据都放在同一个表单下,所以手动在服务器创建一次就可以了。
使用命令:
create database Name charset utf8;
创建一个新的数据库(后接utf8可以在数据库中储存中文信息)。接下来使用:
use Name;
来进入这个数据库下,创建一个数据表:
create table table_name(id INT, value DOUBLE);
成功之后,使用:
insert into table_name values(data1, data2);
来向表中加入记录,接下来使用:
select * from table_name;
来检查记录是否创建好。最终的效果如图:
至此已经创建好了准备存入数据的表单,下面修改数据库的配置使其可以被外部访问(数据库默认只能从本地访问)。
3.配置数据库可以被外部访问
1)创建用于外部登录的用户
外部登录需要一个账号和密码,为了安全性考虑,不能直接使用root来从外部登录数据库,因此这里创建一个新的用户,这个用户有对刚刚新建数据库的所有权限,设置密码的同时允许从任意设备登录数据库。
create user 'user_name'@'%' identified by 'xxxxx';
创建一个可以从任意IP(代码中'%')登录的用户,授权对刚刚创建数据库的全部权限:
grant all privileges on database_name.* to "user_name"@'%';
2)修改MySQL配置使其可以被外部访问到
现在使用“exit”命令退出sql命令状态,进入Linux命令行,使用cd命令进入etc/mysql/mysql.conf.d文件夹,使用vim命令修改文件mysqld.cnf。
将“bind-address”改为“0.0.0.0”表示监听所有端口。之后重启服务,之后查看服务状态,绿色表示一切正常:
service mysql restart
service mysql status
3)防火墙放通SQL服务
按照上面放通防火墙的方式,可以直接选择默认的放通规则。
这样之后可以使用MySQL_workbench来测试连接,也可以不用。(按照步骤来的话一般不会出现问题)
至此MySQL服务已经部署完毕,并且创建好了外部访问用户以及开通了监听端口。下一步将写入数据库的操作结合起来,完善上述的Python程序。
三、Python 接入 MySQL
1.安装库pymysql
Ubuntu最新版自带Python3的运行环境,但是并没有内置我们所需要用到的pymysql库,所以在此先安装Python的库管理工具pip。输入命令回车,之后输入y确认,开始安装pip:
apt install python3-pip
安装完成之后,输入命令:
pip3 install PyMySQL
安装pymsql库,以支持Python连接数据库。
2.Python操作数据库
这里直接在上一个server1.py的基础上增加连接数据库并写入的功能。
import socket # 导入socket库
import threading # 导入多线程库
import time # 导入暂停时间库
import pymysql # 导入操作数据库的库
# 创建Socket(基于IPv4和TCP协议)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定监听端口:
s.bind(('xx.x.x.x', 9999))
s.listen(5) # 监听,传入的参数指定等待连接的最大数量
print('Waiting for connection...')
# 建立线程函数
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!')
# 连接数据库
database = pymysql.connect(host="xx.xx.xxx.xx",
user="user_name",
password="xxxxxxx",
database="My_Server")
cur = database.cursor() # 取得游标
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(
('Data received is: %s' % data.decode('utf-8')).encode('utf-8'))
# 转换数据类型并且存入数据库中
data_double = float(data.decode('utf-8'))
sql = "insert into data1 (id, value) values(2, %lf)" # SQL语句
cur.execute(sql, data_double)
database.commit() # 完成修改之后一定要提交,否则不生效
# 关闭连接
cur.close()
database.close()
sock.close()
print('Connection from %s:%s closed.' % addr)
# 开始监听
while True:
# 接受一个新连接
sock, addr = s.accept()
# 创建新线程来处理TCP连接
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
因为上面创建的数据表中只有id和value两个数字量,所以对终端发送的数据需要稍作修改,仍然发送字符串,但是内容是数字了。
使用WinSCP将修改后的服务器端Python文件部署到服务器,现在服务器上运行,之后在本地运行终端程序。
终端运行结果:
服务器运行结果:
现在进入数据库检验是否存入刚刚发送的数据:
可以看到现在已经增加了一行新的数据,数据库存储完成。
至此已经实现了终端发送数据到服务器,服务器接收并储存到数据库的过程。下一步将使用XMLHttpRequest向服务器发送数据请求,同样由Python相应返回数据。