Anaconda是1个常用的python包管理程序,里面可以设置好多个python环境。
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2021.05-Linux-x86_64.sh --no-check-certificate
sh Anaconda3-2021.05-Linux-x86_64.sh
然后提示你是否同意,输入yes
安装过程中会询问你安装的位置,一般不用更改,输入回车就行,它会自动解压缩
最后会提示是否初始化Anaconda的一些配置,记得输入yes
vim ~/.bashrc #编辑环境配置文件
export PATH="~/anaconda3/bin:$PATH" # 在第一行加入这个
vim 输入 i 可以编辑,编辑好了之后按 Esc, 然后输入 :wq 保存修改
source ~/.bash_profile
最后验证一下是否配置成功,没有保存的话就是配置成功了!
conda create --name ais_env python=3.8 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda activate ais_env
pip install pymysql
将服务代码上传到服务器的 ais_server 目录下,文件如下图:
ais_udp_server.py:UDP服务代码
database_mysql.py:数据库接口
test_client.py:测试UDP客户端
# 这是 UDP 服务端
import socket
import datetime
import logging
from database_mysql import DataBaseMySQL
class MySqlDal:
def __init__(self):
self.db_mysql = DataBaseMySQL()
def __del__(self):
self.db_mysql.close()
# 插入AIS原始数据
def insert_ais_raw_data(self, type, data, parse_state, ct, mt):
db = self.db_mysql
str_sql = "INSERT INTO ais_raw_data (TYPE,DATA,parse_state,ct,mt) VALUES (%s,%s,%s,%s,%s)"
return db.insert(str_sql, [type, data, parse_state, ct, mt])
# 插入AIS动态数据
def insert_ais_dynamic_data(self, raw_id, mmsi, lon, lat, speed, head_dir, track_dir, state, recv_time, ct):
db = self.db_mysql
str_sql = "INSERT INTO ais_dynamic_data (raw_id, mmsi, lon, lat, speed, head_dir, track_dir, state, " \
"recv_time, ct) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) "
return db.insert(str_sql, [raw_id, mmsi, lon, lat, speed, head_dir, track_dir, state, recv_time, ct])
# 插入AIS静态数据
def insert_ais_static_data(self, raw_id, mmsi, ship_name, imo, call_no, ship_form, ship_draught, ship_length,
ship_width, destination, eta, recv_time, ct):
db = self.db_mysql
str_sql = "INSERT INTO ais_static_data (raw_id, mmsi, ship_name, imo, call_no, ship_form, ship_draught, " \
"ship_length, ship_width, destination, eta, recv_time, ct) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
"%s,%s,%s) "
return db.insert(str_sql,
[raw_id, mmsi, ship_name, imo, call_no, ship_form, ship_draught, ship_length, ship_width,
destination, eta, recv_time, ct])
# 更新解析结果
def update_ais_parse_state(self, id, state, mt):
db = self.db_mysql
str_sql = "UPDATE ais_raw_data SET parse_state = %s, mt = %s WHERE id = %s"
return db.update(str_sql, [state, mt, id])
dal = MySqlDal()
# HOST_NAME = socket.gethostname()
# HOST = socket.gethostbyname(HOST_NAME) # 主机号可为空白 HOST = ""
HOST = '0.0.0.0' # 这里有个坑,服务ip需要写0.0.0.0,不能使用127.0.0.1,不然内网和外网其他机器都访问不了,只能本机访问该服务
PORT = 9504
ADDR = (HOST, PORT) # 地址与端口
BUF_SIZE = 10240 # 接收数据缓冲大小
UDPSerSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建udp服务器套接字
UDPSerSock.bind(ADDR) # 套接字与地址绑定-服务端特有
print(ADDR)
encodeing = "gb18030"
# encodeing = "utf-8"
while True:
# 接收客户端发来的字节数组-此处监听
data, addr = UDPSerSock.recvfrom(BUF_SIZE) # 接收客户端发来的字节数组,data.decode()='char',data.upper()='bytes'
data_str = data.decode(encodeing)
print("{} Data Receive from Client {} --> {}".format(datetime.datetime.now(), addr, data_str))
if data_str is None:
response_str = "Error: Data is None!"
elif not data_str.startswith("@"):
response_str = "Error: Format error 1!"
else:
data_array = data_str.replace("@", "").strip(' ').split(",")
if len(data_array) == 8:
# 动态数据
ret = dal.insert_ais_raw_data(1, data_str, 0, datetime.datetime.now(), datetime.datetime.now())
if ret is not None:
try:
raw_id = ret
mmsi = data_array[0]
lon = 0 if len(data_array[1].strip(" ")) == 0 else float(data_array[1].strip(" "))
lat = 0 if len(data_array[2].strip(" ")) == 0 else float(data_array[2].strip(" "))
speed = 0 if len(data_array[3].strip(" ")) == 0 else float(data_array[3].strip(" "))
head_dir = 0 if len(data_array[4].strip(" ")) == 0 else float(data_array[4].strip(" "))
track_dir = 0 if len(data_array[5].strip(" ")) == 0 else float(data_array[5].strip(" "))
state = 0 if len(data_array[6].strip(" ")) == 0 else int(data_array[6].strip(" "))
recv_time = 0 if len(data_array[7].strip(" ")) == 0 else int(data_array[7].strip(" "))
ret1 = dal.insert_ais_dynamic_data(raw_id, mmsi, lon, lat, speed, head_dir, track_dir, state, recv_time,
datetime.datetime.now())
if ret1 is not None:
response_str = "Success!"
dal.update_ais_parse_state(raw_id, 1, datetime.datetime.now())
else:
response_str = "Error: Insert parse data error!"
dal.update_ais_parse_state(raw_id, -2, datetime.datetime.now())
except Exception as e:
logging.error('数据解析失败:%s' % e)
response_str = "Error: Parse error!"
dal.update_ais_parse_state(raw_id, -1, datetime.datetime.now())
else:
response_str = "Error: Insert error!"
elif len(data_array) == 11:
# 静态数据
ret = dal.insert_ais_raw_data(2, data_str, 0, datetime.datetime.now(), datetime.datetime.now())
if ret is not None:
try:
raw_id = ret
mmsi = data_array[0]
ship_name = data_array[1]
imo = data_array[2]
call_no = data_array[3]
ship_form = data_array[4]
ship_draught = 0 if len(data_array[5].strip(" ")) == 0 else float(data_array[5].strip(" "))
ship_length = 0 if len(data_array[6].strip(" ")) == 0 else float(data_array[6].strip(" "))
ship_width = 0 if len(data_array[7].strip(" ")) == 0 else float(data_array[7].strip(" "))
destination = data_array[8]
eta = 0 if len(data_array[9].strip(" ")) == 0 else int(data_array[9].strip(" "))
recv_time = 0 if len(data_array[10].strip(" ")) == 0 else int(data_array[10].strip(" "))
ret2 = dal.insert_ais_static_data(raw_id, mmsi, ship_name, imo, call_no, ship_form, ship_draught,
ship_length, ship_width, destination, eta, recv_time,
datetime.datetime.now())
if ret2 is not None:
response_str = "Success!"
dal.update_ais_parse_state(raw_id, 1, datetime.datetime.now())
else:
response_str = "Error: Insert parse data error!"
dal.update_ais_parse_state(raw_id, -2, datetime.datetime.now())
except Exception as e:
logging.error('数据解析失败:%s' % e)
response_str = "Error: Parse error!!"
dal.update_ais_parse_state(raw_id, -1, datetime.datetime.now())
else:
response_str = "Error: Insert error!"
else:
response_str = "Error: Format error 2!"
# 向客户端发送字节数组
UDPSerSock.sendto(bytes(response_str, encodeing), addr) # 向客户端发送字节数组, bytes("char", "utf-8")
print("{} Response Sentend --> {}".format(datetime.datetime.now(), response_str))
pass
UDPSerSock.close() # 关闭服务端socket
import pymysql
import logging
class DataBaseMySQL:
def __init__(self):
try:
self.connection = pymysql.connect(host="这里填写数据库服务器IP",
user="这里填写用户名",
pass删除这个word="这里填写PW",
port=这里填写端口号,
database="这里填写数据库名",
charset='utf8')
# "vn_vm_center"
self.cursor = self.connection.cursor()
except Exception as e:
logging.error('数据库连接错误:%s' % e)
raise
def execute(self, sql):
conn = self.connection
try:
cur = self.cursor
cur.execute(sql)
conn.commit()
return True
except Exception as e:
logging.error('数据执行失败:%s' % e)
conn.rollback()
return False
def query(self, sql, data):
cur = self.cursor
cur.execute(sql, data)
res = cur.fetchone()
return res
def query_all(self, sql, data):
cur = self.cursor
cur.execute(sql, data)
res = cur.fetchall()
return res
def insert(self, sql, data):
conn = self.connection
try:
cur = self.cursor
cur.execute(sql, data)
res = conn.insert_id()
conn.commit()
return res
except Exception as e:
logging.error('数据新增执行失败:%s' % e)
conn.rollback()
return None
def insert_many(self, sql, datas):
conn = self.connection
try:
cur = self.cursor
# 执行sql语句
cur.executemany(sql, datas)
# 提交到数据库执行
conn.commit()
except Exception as e:
# 如果发生错误则回滚
print(e)
print(sql)
print(datas)
conn.rollback()
logging.error('数据新增执行失败:%s' % e)
def update(self, sql, data):
conn = self.connection
try:
cur = self.cursor
cur.execute(sql, data)
conn.commit()
return True
except Exception as e:
logging.error('数据更新执行失败:%s' % e)
conn.rollback()
return False
def close(self):
self.cursor.close()
self.connection.close()
# 这是 UDP 客户端
import socket
HOST = '127.0.0.1' # 本机测试
PORT = 9504 # 端口号
BUFSIZ = 10240 # 接收消息的缓冲大小
ADDR = (HOST, PORT)
print(ADDR)
UDPCliSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建客户端套接字
while True:
##step.1##
data = input('输入发送内容> ')
if not data:
break
UDPCliSock.sendto(bytes(data, 'gb18030'), ADDR) # 由客户端向服务端发送【字节数组】
##step.2##
data, ADDR = UDPCliSock.recvfrom(BUFSIZ) # 接收服务端回应的【字节数组】
if not data: # 如果接收服务器信息失败,或没有消息回应
break
print('服务器:', ADDR, str(data, 'gb18030')) # 打印回应消息
pass
UDPCliSock.close() # 关闭客户端socket
cd /ais_server/
conda activate ais_env
nohup python -u ais_udp_server.py > log.txt 2>&1 &
查看进程
ps -ef|grep python
关闭进程
kill -9 19913
查看日志
tail -f 1000 /ais_server/log.txt
如何查看端口占用
$: netstat -anp | grep 9504
udp 0 0 0.0.0.0:9504 0.0.0.0:* 4793/python
强制杀掉进程:通过pid
$: kill -9 4793
$: netstat -anp | grep 8888
可以通过 test_client.py 客户端进行本机测试,这里使用 SocketTool.exe 工具进行验证,如下图:
参考:https://blog.csdn.net/weixin_41275726/article/details/124529674