我用QT编写了一个用户界面,用来操作局域网中的设备(网络摄像头之类),
我通过QUdpSocket组播的方式把我的Mac地址打包成Xml数据报,然后发送出去,
设备通过嵌入式编程接收并解析我发的数据报,
然后设备将自己的Mac打包成Xml回执报文,发送到解析得出的Mac地址上(也就是我的网卡上),
然后我获取到数据解析得到他的Mac地址
我为设备分配一个IP然后将设置结果以单播形式发送到他的网卡上
目前的问题是,我的数据组播出去,且他已经成功解析并向我发送了回执
但是我却接收不到他的报文,自然也就无法解析
我的代码如下:
socketxml.h文件
--------------------------------
#ifndef SOCKETXML_H
#define SOCKETXML_H
#include <QThread>
#include <QString>
#include <QtNetwork>
#include <QTimer>
#include <QByteArray>
#include "global.h"
class SocketXml : public QThread
{
Q_OBJECT
public:
SocketXml();
~SocketXml();
public slots:
void SendXmlBuf(QString str); //发送Xml数据
void RecvXmlBuf(); //接收Xml数据
protected:
void run(); //处理收发操作线程
private:
QUdpSocket *udpsocket;
};
#endif // SOCKETXML_H
************************************************************************************************************
socketxml.cpp
----------------------------------------
#include "socketxml.h"
#include <QDebug>
SocketXml::SocketXml()
{
udpsocket= new QUdpSocket(this);
//udpsocket->bind(QHostAddress::AnyIPv4,Global::Instance().port,QUdpSocket::ReuseAddressHint);
udpsocket->bind(Global::Instance().port,QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
udpsocket->setSocketOption(QAbstractSocket::MulticastLoopbackOption,1);
udpsocket->setSocketOption(QAbstractSocket::MulticastTtlOption,255);
udpsocket->joinMulticastGroup(QHostAddress(Global::Instance().Mucst_ip));
}
SocketXml::~SocketXml()
{
quit();
wait();
delete udpsocket;
}
/*!
* \brief SocketXml::SendXmlBuf
* \param str
* 发送数据
*/
void SocketXml::SendXmlBuf(QString str)
{
int len=udpsocket->writeDatagram( //调用QUdpSocket成员函数writeDatagram()发送数据
str.toLatin1().data(), //将数据转换成字符串(char*)格式
str.length(), //发送字符串长度
//QHostAddress(Global::Instance().Mucst_ip), //发送数据到组播IP
QHostAddress::Broadcast, //发送到组内所有主机
Global::Instance().port); //发送端口
if(len!=-1)
{
qDebug()<<"writeDatagram已发送"<<len<<"字节数据";
}
else
{
qDebug()<<"发送失败";
}
}
/*!
* \brief SocketXml::RecvXmlBuf
* 接收数据
*/
void SocketXml::RecvXmlBuf()
{
qDebug()<<"正在检测...";
while(udpsocket->hasPendingDatagrams())
{
qDebug()<<"hasPendingDatagrams检测到数据包";
QByteArray byte;
QHostAddress getaddr;
quint16 getport;
byte.resize(udpsocket->pendingDatagramSize());
int strsize=udpsocket->readDatagram(
byte.data(), //数据内容
byte.size(), //数据大小
&getaddr, //发送者地址
&getport); //发送者端口
qDebug()<<"readDatagram读入"<<strsize<<"字节数据";
Global::Instance().RecvBuf.append(byte);
qDebug()<<"发送者地址:"<<getaddr<<"发送者端口:"<<getport;
}
}
/*!
* \brief SocketXml::run
* 重写QThread虚函数run(),用于添加线程工作
*/
void SocketXml::run()
{
if(Global::Instance().flag)
{
while(!Global::Instance().SendBuf.isEmpty())
{
SendXmlBuf(Global::Instance().SendBuf.dequeue()); //每次发送队首,发送完删除当前队首
}
RecvXmlBuf(); //发完数据进入接收状态
Global::Instance().flag=false; //接收完数据停止工作
}
exec();
}
听说从网卡中收发数据要用到原始套接字
但是有两个问题,原始套接字是基于Linux系统内核的
首先必须有超级用户权限才能使用原始套接字
QT Creator无法获得超级用户权限
其二我的这款软件是要实现跨平台运行的
比如我现在是在Windows下做开发
这样一来Linux的头文件就识别不了
如果我要用winpcap库进行Windows下的底层通信就必须配置Winpcap环境
这样一来就无法在Linux系统下使用
以后说不定还会在安卓平台IOS平台使用
况且用户也不可能再在用软件之前还要开超级权限,还要配置环境
所以我想了解一下,QT库中有没有能实现这种底层通信的类
或者我和设备之间是否需要这样底层的通信