鑫通态 HMI 各系列(C,M)支持网口,可通过代码自定义 Socket 客户端来满足不同用户需求。
!注意
自定义 Socket 适用于有编程基础的用户,操作不当可能导致宕机。
将 Socket 客户端定义为 C++类是一个很好的实践,特别是当你在多线程环境中工作时。这不仅提高了代码的组织性和可维护性,还帮助你更好地管理资源和同步问题。
!提醒
此处.h 文件需要从其他地方复制一份,名字可随意更改。
UserPort 类说明:2 个类成员分别为**客户端句柄和读写锁。三个成员函数分别为,连接函数和读操作和写操作**。
#ifndef Socket_H
#define Socket_H
#include "util/DateUtil.h"
#include "util/Util.h"
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#ifndef __arm__
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <unistd.h>
#endif
class UserPort
{
public:
UserPort() : handle(-1) {}
~UserPort() {
if (handle != -1) {
util::Util::socketClose(handle);
}
}
int PortConnect(const char *hostname, int port) {
std::unique_lock<std::mutex> lock(mtx);
if (handle != -1) {
util::Util::socketClose(handle);
}
handle = Util::socketConnect(hostname, port);
return handle;
}
int PortWrite(const char *buf, int len) {
std::unique_lock<std::mutex> lock(mtx);
if (handle == -1) {
return -1;
}
return send(handle, static_cast<const char*>(buf), len, 0);
}
int PortRead(char *buf, int len) {
std::unique_lock<std::mutex> lock(mtx);
if (handle == -1) {
return -1;
}
return recv(handle, buf, len, 0);
}
private:
int64_t handle;
std::mutex mtx;
};
#endif /* Socket_H */
3.1 在 HmiApp.h 自定义区自定义 Sokcet 类指针。
3.2 创建这个 Socket 类实例
选择在 HMI onReady()里面新建这个 Socket 类
说明:Socket 连接操作需要放在**全局的公共页的异步线程**,因为连接操作是个耗时操作,如果放在主线程会影响 UI 导致 UI 卡顿。
void Frm04::wMAsyncWorker4_ref_cb(uint16_t code, LvEvent e) {
while(1){
string UserHost;
int UserPort;
int UserState;
vm->getChar("主机地址", UserHost);
vm->getInt("端口", UserPort);
int Result = hmiApp->SocketHandel->PortConnect(UserHost.c_str(), UserPort);
if(Result>0){ //连接成功
vm->setInt("连接状态", 1);
while(1){
//循环读操作
char Readbuf[1024] = { 0 };
int ReadByts = hmiApp->SocketHandel->PortRead(Readbuf, 256);
if(ReadByts>0){
string ReadString(Readbuf, ReadByts);
vm->setChar("接受缓存", ReadString);
}
if(ReadByts<0)break; //断开连接
Util::sleepFor(300); // 休眠300毫秒,避免CPU空转
}
}
Util::sleepfor(3000); //休眠3秒 重新连接
}
}
char Readbuf[1024] = { 0 };
int ReadByts = hmiApp->SocketHandel->PortRead(Readbuf, 256);
if(ReadByts>0){
string ReadString(Readbuf, ReadByts);
vm->setChar("接受缓存", ReadString);
}
string serialized;
vm->getChar("发送缓存", serialized);
int state = hmiApp->SocketHandel->PortWrite(serialized.c_str(),serialized.length());