#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "cJSON.h"
#define N 2000
int main(int argc, char const *argv[])
{
int broadfd;
//./server <port> <protocol>
if (argc < 3)
{
printf("usage: %s <port> <protocol>\n", argv[0]);
return -1;
}
//创建一个socket文件描述符
broadfd = socket(AF_INET, SOCK_DGRAM, 0);
if (broadfd < 0)
{
perror("sock err");
return -1;
}
//绑定套接字(ip+port)
struct sockaddr_in addr, cliaddr;
ssize_t len;
char buf[N] = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1])); //端口号
//自动绑定所有的本机网卡的地址
addr.sin_addr.s_addr = INADDR_ANY;
int addrlen = sizeof(addr);
//将套接字与所选ip绑定
if (bind(broadfd, (struct sockaddr *)&addr, addrlen) < 0)
{
perror("bind err");
return -1;
}
//接收消息,判断是否为私有协议
while (1)
{
len = recvfrom(broadfd, buf, N, 0, (struct sockaddr *)&cliaddr, &addrlen);
if (len > 0)
{
if (!strncmp(buf, argv[2], strlen(argv[2])))
{
printf("recv data=%s\n", buf);
bzero(buf, N);
strcpy(buf, "yes");
sendto(broadfd, buf, N, 0, (struct sockaddr *)&cliaddr, addrlen);
bzero(buf, N);
break;
}
else
{
printf("包不正确\n");
usleep(100000);
continue;
}
}
else
{
perror("recv err");
exit(0);
}
}
//建立服务器
int tcpfd = socket(AF_INET, SOCK_STREAM, 0);
if (tcpfd < 0)
{
perror("sock2 err");
return -1;
}
if (bind(tcpfd, (struct sockaddr *)&addr, addrlen) < 0)
{
perror("bind err");
return -1;
}
if (listen(tcpfd, 5) < 0)
{
perror("listen err");
return -1;
}
//接受客户端连接
int clifd = accept(tcpfd, NULL, NULL);
//int clifd = accept(tcpfd, (struct sockaddr *)&cliaddr, &addrlen);
if (clifd < 0)
{
perror("accept err");
return -1;
}
printf("accept succ\n");
while (1)
{
bzero(buf, N);
//usleep(1000000);
read(clifd, buf, N);
cJSON *root = cJSON_Parse(buf);
if (NULL == root)
{
printf("Parse err\n");
return -1;
}
bzero(buf, N);
printf("%s\n", cJSON_Print(root)); //打印测试
cJSON *type = cJSON_GetObjectItem(root, "type");
if (!strncmp(type->valuestring, "1", 2))
{
if (access("./table.json", F_OK) == 0)
{
//电表存在
printf("电表存在\n");
strcpy(buf, "{\"type\": \"1\",\"result\": 0,\"up_config\": false,\"data\": {\"mqtt_config\": {\"mqtt_addr\": \"192.168.1.2\",\"mqtt_port\": 1883},\"video_config\": {\"video_addr\": \"192.168.8.8\",\"video_port\": 8888},\"update_config\": {\"type\": 1,\"period\": 5}}}");
write(clifd, buf, strlen(buf));
bzero(buf, N);
usleep(3000000);
//发送电表
int fd = open("./table.json", O_RDONLY, 0666);
int num = read(fd, buf, N);
printf("点表字符个数:%d\n", num);
write(clifd, buf, strlen(buf));
bzero(buf, N);
usleep(100000);
}
else
{
//创建JSON格式 发送数据
strcpy(buf, "{\"type\": \"1\",\"result\": 1,\"up_config\": true}");
write(clifd, buf, strlen(buf));
bzero(buf, N);
usleep(1000000);
strcpy(buf, "./");
strcat(buf, "table.json");
int fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
bzero(buf, N);
// 将电表写进去
int num = read(clifd, buf, N);
printf("文件长度:%d\n", num);
write(fd, buf, num + 1);
close(fd);
printf("%s\n", buf);
bzero(buf, N);
usleep(1000000);
printf("点表接受成功\n");
}
}
else if (!strncmp(type->valuestring, "2", 2))
{
strcpy(buf, "{\"type\": \"2\",\"result\": 1}");
write(clifd, buf, strlen(buf));
bzero(buf, N);
usleep(1000000);
//
int fd = open("./table.json", O_WRONLY | O_CREAT | O_TRUNC, 0666);
int num = read(clifd, buf, N);
printf("读取字符个数:%d\n", num);
if (write(fd, buf, strlen(buf)) < 0)
{
perror("write err221");
return -1;
}
close(fd);
bzero(buf, N);
printf("点表接受成功\n");
//
// strcpy(buf, "{\"type\": 2,\"result\": 1}");
// write(clifd, buf, strlen(buf) );
// bzero(buf, N);
}
else if (!strncmp(type->valuestring, "3", 2))
{
strcpy(buf, "{\"type\": \"3\",\"result\": 1}");
write(clifd, buf, strlen(buf));
bzero(buf, N);
usleep(100000);
}
}
close(broadfd);
close(tcpfd);
close(clifd);
return 0;
}
QT客户端代码
#include "search_device.h"
#include "ui_search_device.h"
#include <QFile>
//type
//1:获取运行时必要的参数信息
//2:点表下发
//3:心跳包
Search_device::Search_device(QWidget *parent) :
QWidget(parent),
ui(new Ui::Search_device)
{
ui->setupUi(this);
//1.创建QUdpSocket对象
UdpSocket = new QUdpSocket(this);
//2.连接接收数据信号和槽
connect(UdpSocket,SIGNAL(readyRead()),this,SLOT(on_pushButton_search_clicked()));//readRead()读取数据的信号
//UDP接收协议,获得设备IP与port
connect(UdpSocket,SIGNAL(readyRead()),this,SLOT(ReadyRead_Udp_Slots()));
//创建TCP Socket
TCPsocket =new QTcpSocket(this);
//点击IP,触发赋值槽函数;
connect(ui->listWidget_search,SIGNAL(itemClicked(QListWidgetItem*)),
this,SLOT(itemClickedIPSlot(QListWidgetItem*)));
//点击port,触发赋值;
connect(ui->listWidget_search,SIGNAL(itemClicked(QListWidgetItem*)),
this,SLOT(itemClickedportSlot(QListWidgetItem*)));
//点击连接按钮,与Tcp
connect(ui->ConnectButton,SIGNAL(clicked()),this,SLOT(buttonConnectSlots()));
//TCP通信
connect(TCPsocket,SIGNAL(readyRead()),this,SLOT(ReadyRead_Tcp_Slots()));
//发送 3种type类型
connect(ui->pushButton_type,SIGNAL(clicked()),this,SLOT(type_send_Slots()));
}
Search_device::~Search_device()
{
delete ui;
delete TCPsocket;
delete UdpSocket;
}
void Search_device::on_pushButton_search_clicked()
{
//发送协议
UdpSocket->writeDatagram("aaa",4,QHostAddress("192.168.50.255"),7777);//writeDatagrad()发送数据,参数:内容,大小,地址,端口
}
void Search_device::ReadyRead_Udp_Slots()
{
QHostAddress myip;//获取ip
quint16 myport;//获取端口
QByteArray data;
while(UdpSocket->hasPendingDatagrams()) //匹配到对应的设备,并接收到设备返回的“yes”
{
data.resize(UdpSocket->pendingDatagramSize());
UdpSocket->readDatagram(data.data(),data.size(),&myip,&myport);
QString buf = data.data();
if(buf == "yes")
{
ui->listWidget_search->addItem(myip.toString()+"and"+QString::number(myport));
}
}
}
void Search_device::itemClickedIPSlot(QListWidgetItem *item)
{
ip=item->text().left(13);
qDebug() << "ip:" ;
qDebug() << ip <<endl;
}
void Search_device::itemClickedportSlot(QListWidgetItem *item)
{
port=item->text().right(4).toInt();
qDebug() << "port:" ;
qDebug() << port <<endl;
}
void Search_device::buttonConnectSlots()
{
// 发起TCP连接请求
qDebug() << "发起请求连接" ;
TCPsocket->connectToHost(ip,port,QIODevice::ReadWrite);//QIODevice类是所有输入/输出设备的基类而QIODevice::ReadWrite则表示该设备既可以读取数据,也可以写入数据。
qDebug() << "连接已完成" ;
qDebug() << ip <<86;
qDebug() << port <<87;
}
void Search_device::type_send_Slots()
{
QJsonObject json;//创建json对象
QTextStream output(TCPsocket);//用于创建一个QTextStream对象,用于输出文本数据。它返回一个QTextStream对象,你可以使用该对象来写入数据到输出设备,如控制台、文件或网络套接字
if(ui->comboBox->currentText() == "1")
{
json.insert("type","1");
QJsonDocument doc(json);//QJsonDocument是Qt中用于处理JSON文档的类,它提供了创建、读取、写入和操作JSON数据的方法。
output << doc.toJson();//toJson()将JSON文档转换为字符串
qDebug() << doc.toJson();
}
else if(ui->comboBox->currentText() == "2")
{
json.insert("type","2");
QJsonDocument doc(json);//QJsonDocument是Qt中用于处理JSON文档的类,它提供了创建、读取、写入和操作JSON数据的方法。
output << doc.toJson();//toJson()将JSON文档转换为字符串
qDebug() << doc.toJson();
}
else if(ui->comboBox->currentText() == "3")
{
json.insert("type","3");
QJsonDocument doc(json);//QJsonDocument是Qt中用于处理JSON文档的类,它提供了创建、读取、写入和操作JSON数据的方法。
output << doc.toJson();//toJson()将JSON文档转换为字符串
qDebug() << doc.toJson();
}
}
void Search_device::ReadyRead_Tcp_Slots()
{
qDebug() << "有消息到了"<<endl;
QByteArray Tcpdata = TCPsocket->readAll(); //把接收到网关发来的数据全部读到Tcpdata里面;
QString buff = Tcpdata; //消息转字符串
qDebug() << buff <<endl;
QJsonParseError err;
QJsonDocument jsonMsg(QJsonDocument::fromJson(buff.toLatin1(),&err));//fromJson()函数用于将JSON格式的字符串转换为QJsonDocument对象
if(err.error != QJsonParseError::NoError)
{
qDebug() << "Json格式错误!!";
return;
}
QJsonObject Json = jsonMsg.object();//.object获取QJsonDocument对象中的根级别的QJsonObject
if(Json.value("version") != QJsonValue::Undefined)
{
QString version = Json.value("version").toString();
ui->textBrowser->setText(version);
return;
}
QString type = Json.value("type").toString();
//buff.append("type:");
buff.clear();
if(type == "1")
{
QString up_config = Json.value("up_config").toString();
if(up_config == "true")
{
qDebug() << "没有点表,需要下发点表!!";
ui->listWidget->clear();
ui->listWidget->addItem("没有点表,需要下发点表!");
//QJsonObject json;
// 弹窗
QString filter = "视频(*.mp4 *.avi);;所有文件(*)";
con:
QString path = QFileDialog::getOpenFileName(this,"没有点表,需要下发点表!","F:/",filter);
// 判断选择有效性
if(path == "" && readPath == "")
{
QMessageBox::warning(this,"提示","请选择要读取的文件!");
goto con;
}
readPath = path;
// 显示
ui->textBrowser->clear();
ui->textBrowser->append(readPath);
QFile readFile(readPath);
readFile.open(QIODevice::ReadOnly);
// 获得可读的数据量
qint64 total = readFile.size();
// 字节数组类
QByteArray buffer;
buffer = readFile.read(total+1);
//QString buff = buffer;
// json.insert("type","2");
// QJsonObject data;
// data.insert("file_name","table.json");
// data.insert("flag","start");
// data.insert("file_len",560);
// json.insert("data",data);
//QJsonDocument document(json); //转化成JSON字符串
//QByteArray aaa = document.toJson(); //放入数组aaa中
TCPsocket->write(buffer); //TCP发送
TCPsocket->flush();
}
else if(up_config == "false")
{
qDebug()<<"有点表,不需要下发!";
ui->listWidget->clear();
ui->listWidget->addItem("有点表,不需要下发点表,点表信息已显示");
ui->textBrowser->clear();
ui->textBrowser->append((buff=TCPsocket->readAll()));
// QJsonObject json3;
// json3.insert("type","3");
// QJsonDocument document1(json3);
// QByteArray bbb = document1.toJson();
// TCPsocket->write(bbb);
// TCPsocket->flush();
// ui->listWidget->clear();
// ui->listWidget->addItem("心跳包已连接");
buff.clear();
}
}
else if(type == "2") //下发点表
{
// QJsonObject Json2 = Json.value("data").toObject();
// QString flag = Json2.value("flag").toString();
// if(flag == "start")
// {
// 弹窗
QString filter = "所有文件(*)";
ccon:
QString path = QFileDialog::getOpenFileName(this,"没有点表,需要下发点表!","F:/",filter);
// 判断选择有效性
if(path == "" && readPath == "")
{
QMessageBox::warning(this,"提示","请选择要读取的文件!");
goto ccon;
}
readPath = path;
// 显示在QTextBrowser
ui->textBrowser->append(readPath);
QFile readFile(readPath);
readFile.open(QIODevice::ReadOnly);
// 获得可读的数据量
qint64 total = readFile.size();
// 字节数组类
QByteArray buffer;
buffer = readFile.read(total+1);
//打开JSON文件
//QFile loadFile("D:/node.json");
// if(!loadFile.open(QIODevice::ReadOnly))
// {
// qDebug() << "could't open projects json";
// return;
// }
//QByteArray allData = loadFile.readAll();
// QString buf = allData;
// QTextStream output(mytcpsocket);
//TCPsocket->write(allData,560); //TCP发送
TCPsocket->write(buffer); //TCP发送
TCPsocket->flush();
}
else if(type == "3")
{
// QJsonObject json5;
// json5.insert("type","3");
// QJsonDocument document3(json5);
// QByteArray ddd = document3.toJson();
// TCPsocket->write(ddd);
// TCPsocket->flush();
ui->listWidget->clear();
ui->listWidget->addItem("心跳包已连接 网关在线");
}
}