这里是CIP资料的协议层级图,讲解协议构造。
ODVA(www.ODVA.org)成立于1995年,是一个全球性协会,其成员包括世界领先的自动化公司。结合其成员的支持,ODVA的使命是在工业自动化中推进开放、可互操作的信息和通信技术。成员团体的基础是其在制定标准和促进通过《共同工业议定书》方面的主要共同利益?), ODVA的媒体独立网络协议,以及CIP–EtherNet/IP的网络适配?, DeviceNet?, CompoNet? 和ControlNet?. ODVA管理这些技术,并在一个通用结构中开发和分发这四个网络的规范,以帮助确保一致性和准确性。下图说明了由四个网络组成的库的组织结构。
中文总线资料和方案?www.jngbus.com
广州金南瓜科技
我们可以看到,其中一个EtherNet/IP是基于TCP/UDP之上。
那么我们就可以理解为,基于socket应用之上就可以了。
如果只是纯应用角度去开发EtherNet/IP,可以借助一些成熟的socket库。奈何我们早期学C++的人,没有那么多成熟模块,都是靠自己撸出来。
把TCP/IP通讯单独做成一个dll
① 目的是后续我们讲解开发modbus tcp、profinet等这些以太网协议时候,就不需要每种协议都单独写一次TCP/UDP通讯了
头文件代码
// 用于TCP/IP通讯
class CTcpCommunication : public CTcpCommExport
{
public:
?? ?CTcpCommunication();
?? ?virtual ~CTcpCommunication();
?? ?// 释放
?? ?void Release();?? ?
?? ?void SetCallback(OnCommDataHandle* pDataCallback, OnCommEventNotify* pEventCallback, void* pObject);
?? ?CResult Connect(const char* pIP, __int32 nPort);?? ??? ?// 连接
?? ?void Disconnect();?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?// 关闭连接
?? ?CResult SendData(const char* pData, __int32 nSize);?? ??? ?// 数据发读
?? ?void SetLanguage(__int32 nType);
protected:
?? ?// 数据接收?? ?
private:
?? ?
?? ?void InitSockWSA();
?? ?void ReleaseSockWSA();
?? ?// 接收数据线程
?? ?void CreateRecvThread();?? ??? ?// 创建接收线程
?? ?void ExitRecvThread();?? ??? ??? ?// 退出接收线程
?? ?static void RunRecvThread(void* lp);
?? ?void RecvHandle();
?? ?bool IsExitThread();
?? ?void OneRecvData();?? ??? ??? ??? ?// 一次接收数据
?? ?void StartRecvData();?? ??? ??? ?// 开始接收数据
?? ?void StopRecvData();?? ??? ??? ?
?? ?void CloseConnect();?? ??? ??? ?// 关闭通讯
private:
?? ?CData m_pData;
};
② socket处理很简单,其实就是围绕着收发
connect和send、recv
至于性能问题,就是如何优化在这处理和同步问题了。
程序稳定可靠需要靠自身的积累了。
建立通讯代码。
if(m_hSock == INVALID_SOCKET)
{
m_hSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(m_hSock != INVALID_SOCKET)
{
if(connect(m_hSock, (struct sockaddr*)&m_pSA, sizeof(m_pSA)) < 0)
{
closesocket(m_hSock);
m_hSock = INVALID_SOCKET;
// MC TCP连接失败,请查看网络是否通讯上、或者端口问题
return CResult(TCP_SOCKET_CONNECT_FAIL, GetLanguage(TCP_SOCKET_CONNECT_FAIL));
}
}
else
{
return CResult(TCP_SOCKET_CREATE_FAIL, GetLanguage(TCP_SOCKET_CREATE_FAIL));
}
}
return CResult();
发送数据