⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 en_sock.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*****************************************************************************
**
** File Name
** ---------
**
** EN_SOCK.C
**
*****************************************************************************
*****************************************************************************
**
** Description
** -----------
**
** Ethernet Socket interface.
**
*****************************************************************************
*****************************************************************************
**
** Source Change Indices
** ---------------------
**
** Porting: <none>0----<major>         Customization: <none>0----<major>
**
*****************************************************************************
*****************************************************************************
**                                                                         **
** ETHERNET/IP EXAMPLE CODE                                                **
** COPYRIGHT (c) 2000-2005 ODVA (Open DeviceNet Vendor Association)		   **
**						   & ControlNet International Ltd.                 **
**                                                                         **
** All rights reserved, except as specifically licensed in writing.        **
** Use of the Ethernet/IP Example Protocol Software is subject to          **
** ODVA's and ControlNet International's Terms of Use Agreement.           **
** The following work constitutes example program code and is intended     **
** merely to illustrate useful programming techniques.  The user is        **
** responsible for applying the code correctly.  The code is provided      **
** AS IS without warranty and is in no way guaranteed to be error-free.    **
**                                                                         **
*****************************************************************************
*****************************************************************************
*/


#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif


#include "ab.h"
#ifdef CD_EN_OBJECTS
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "cd.h"
#include "en.h"
#include "en_sock.h"
#include "id.h"       /* Identity Object public interfaces                 */

#include "EcInterface.h"

#define CHECKPOINT(x) 
/*#define CHECKPOINT(x) \
	{\
		char __tmpbuf[1024];\
		sprintf(__tmpbuf,"[CheckPoint]: %s\n",x);\
		OutputDebugString(__tmpbuf);\
	}
*/
/****************************************************************************
**
** Public data
**
*****************************************************************************
*/
UINT32          lECE_connects = 0;         /* Current number of TCP connections */
UINT32          lECE_connects_in = 0;      /* Current number of incoming TCP connections */
UINT32          lECE_connects_out = 0;     /* Current number of outgoing TCP connections */
UINT32          lTotal_lECE_connects = 0;  /* Current number of TCP connections */
UINT32          lTotalProcessed = 0;       /* Total Incoming messages processed */
INT32           lEncapServerPort = 0xaf12;
/****************************************************************************
**
** Private data
**
*****************************************************************************
*/
       ECE      sClass1Ece;
static ECE      sUDPEce;

/*
** Open multicast client connections.  Keep at least one for every
** possible connection. In actuality it will  probably be much less
*/

static MulticastTblType sMulticastTbl[EN_CD_NUM_CLASS_1];
extern ENCAP_OBJ_TARGET list_target_data;

/****************************************************************************
**
** Private services
**
*****************************************************************************
*/


/*---------------------------------------------------------------------------
** en_cd_JoinMulticast( )
**---------------------------------------------------------------------------
*/
UINT32 en_cd_JoinMulticast( struct sockaddr_in *psMc_addr )
{
   INT32           nAvailable;
   struct ip_mreq  sMreq;
   INT32           nConnections;
   struct sockaddr_in sTmp_addr;

   if ( htons( CLASS1_UDP_PORT ) != psMc_addr->sin_port )
   {
/*jjw non default port not yet supported */
      return OE_ERROR;
   }
   sTmp_addr.sin_addr.s_addr = ntohl( psMc_addr->sin_addr.s_addr );
   if ( IN_MULTICAST( sTmp_addr.sin_addr.s_addr ) )
   {
      for ( nConnections = 0;
            nConnections < sizeof sMulticastTbl / sizeof sMulticastTbl[0];
            nConnections++ )
      {
         /*
         ** Run through the list of existing connections, if the multicast
         ** address matches with the one we are going to join, up the
         ** connection count in our record and don't join again
         */

         if ( ( sMulticastTbl[nConnections].iMcastAddr == sTmp_addr.sin_addr.s_addr ) &&
              ( sMulticastTbl[nConnections].iConnections > 0 ) )
         {
            sMulticastTbl[nConnections].iConnections += 1;
            return OK;
         }
         else if ( sMulticastTbl[nConnections].iConnections == 0 )
         {
            nAvailable = nConnections;
         }
      }  /* End for */

      /*
      ** No pre-existing connections for this address, need to add a new one
      */

      sMreq.imr_interface.s_addr = htonl( INADDR_ANY );

      /*
      ** fill in the argument structure to join the multicast group
      ** initialize the multicast address to join
      */

      sMreq.imr_multiaddr.s_addr = htonl( sTmp_addr.sin_addr.s_addr );

      /*
      ** First check to see if this socket is initialized. We may have exceeded the
      ** IP_MAX_MEMBERSHIPS limit and not had the option of opening another
      ** socket.
      */
      if ( sMulticastTbl[ nAvailable ].iSocket == 0 )
         return OE_ERROR;
      if ( setsockopt( sMulticastTbl[ nAvailable ].iSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                     ( char * ) &sMreq, sizeof( sMreq ) ) == OE_ERROR )
      {
         return OE_SOCKET_ERRNO;
      }  /* end if setsockopt  */

      /*
      ** keep track of the multicast groups, and the count of clients listening.
      */

      sMulticastTbl[nAvailable].iConnections = 1;
      sMulticastTbl[nAvailable].iMcastAddr = sTmp_addr.sin_addr.s_addr;
      return OK;
   }  /* end if ( IN_MULTICAST( tmp_addr.sin_addr.s_addr ) ) */

   return OE_ERROR;

}  /* end en_cd_JoinMulticast */


/*---------------------------------------------------------------------------
** en_cd_DropMulticast( )
**---------------------------------------------------------------------------
*/

UINT32 en_cd_DropMulticast( struct sockaddr_in *psMc_addr )
{
   struct ip_mreq  sMreq;
   INT32           nConnections;
   struct sockaddr_in sTmp_addr;

   sTmp_addr.sin_addr.s_addr = ntohl( psMc_addr->sin_addr.s_addr );
   if ( IN_MULTICAST( sTmp_addr.sin_addr.s_addr ) )
   {
      for ( nConnections = 0;
            nConnections < sizeof sMulticastTbl / sizeof sMulticastTbl[0];
            nConnections++ )
      {
         /*
         ** Run through the list of existing connections, if the multicast
         ** address matches with the one we are going to join, lower the
         ** connection count in our record
         */

         if ( ( sMulticastTbl[nConnections].iMcastAddr == sTmp_addr.sin_addr.s_addr ) &&
              ( sMulticastTbl[nConnections].iConnections > 0 ) )
         {
            /*
            ** Check to make sure no one else is listening to this address.  If
            ** they are just return and don't leave the multicast group
            */

            if ( sMulticastTbl[nConnections].iConnections > 1 )
            {
               sMulticastTbl[nConnections].iConnections -= 1;   /* lower count */
               return OK;
            }  /* end if connections > 0 */

            /*
            ** We found the multicast address and no
            ** one else is listening
            */

            break;

         }  /* end if same multicast connection */

      }  /* End for */

      /*
      ** Check to make sure we really joined this multicast group.  If we
      ** didn't this is a definate programming error
      */

      if ( nConnections == sizeof sMulticastTbl / sizeof sMulticastTbl[0] )
      {
         GS_LogEvent( EN_NO_MULTICAST,
                      0,
                      0,
                      FATAL );
      }

      sMreq.imr_multiaddr.s_addr = htonl( sTmp_addr.sin_addr.s_addr );
      /*
      ** Wind River requires the interface address in order to drop
      ** membership in a multicast connection.  INADDR_ANY will return an
      ** error
      */
      sMreq.imr_interface.s_addr = htonl( list_target_data.sS.s_sock.lSin_addr );
      if ( setsockopt( sMulticastTbl[ nConnections ].iSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                     ( char * ) &sMreq, sizeof( sMreq ) ) == OE_ERROR )
      {
         return OE_SOCKET_ERRNO;
      }  /* end if setsockopt  */

      sMulticastTbl[nConnections].iConnections = 0; /* No more listeners */
      sMulticastTbl[nConnections].iMcastAddr = 0;   /* No more listeners */
      return OK;
   }  /* end if ( IN_MULTICAST( * sTmp_addr.sin_addr.s_addr ) ) */

/*jjw do we really want to return OK if specified address is not Multicast ??*/
   return OK;

}  /* end en_cd_DropMulticast */




/*---------------------------------------------------------------------------
** en_cd_Class1RecvTask( )
**---------------------------------------------------------------------------
*/


TASKRETURN en_cd_Class1RecvTask( TASKPARAM )
{
    INT32          lBytesReceived;
   struct sockaddr_in sClientAddr;
   CPFHDR         *psMsg;
   PKTBUF         *psPacketBuf;
    INT32          lSockFd;
   struct sockaddr_in sSrvrAddr;
   UINT32          lSockAddrSize;
   UINT32          lFlagTrue = ~0;
   UINT32          iConnIndex;
#if defined( IP_MAX_MEMBERSHIPS )
   UINT32          iStatus;
   UINT32          iMulticastSockets;
   UINT32          iIndex;
#endif

   lSockAddrSize = sizeof( struct sockaddr_in );
   UC_SetMem( ( char * ) &sSrvrAddr, 0, sizeof( sSrvrAddr ) );
#ifndef _WIN32
	   sSrvrAddr.sin_len = ( UINT8 ) lSockAddrSize;
#endif
   sSrvrAddr.sin_family = AF_INET;
   sSrvrAddr.sin_addr.s_addr = htonl( INADDR_ANY );
   sSrvrAddr.sin_port = htons( CLASS1_UDP_PORT );

   /*
   ** zero out the client multicast connection table
   */

   UC_SetMem( sMulticastTbl, 0, sizeof sMulticastTbl );
   UC_SetMem( &sClass1Ece, 0, sizeof sClass1Ece );

#if defined( IP_MAX_MEMBERSHIPS )
   /*
   ** The operating system limits the number of multicast connections
   ** per socket (BSD limits to 20).  Therefore we need to open more sockets to handle
   ** the maximum number of Class 1 multicast connections we get .  Currently
   ** this additional functionality is only enabled for the enhanced motorola
   ** fec drivers.  Adding to NT and other operating systems would mean spawning
   ** multiple receive tasks, each maintaining their own segment of the sMulticastTbl.
   */

   iMulticastSockets = ( EN_CD_NUM_CLASS_1 + IP_MAX_MEMBERSHIPS - 1 ) / IP_MAX_MEMBERSHIPS;

   for ( iIndex = 0; iIndex < iMulticastSockets; iIndex++ )
   {
      /*
      ** Need a socket to do anything, fatal if can't get one....
      */

      if ( ( lSockFd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == OE_ERROR )
      {
         GS_LogEvent( EN_SOCKET_ERR,
                      OE_SOCKET_ERRNO,
                      0,
                      FATAL );
         GS_DeleteTask( 0 );
      }

      iStatus = setsockopt( lSockFd, SOL_SOCKET, SO_REUSEPORT, ( char * ) &lFlagTrue,
                            sizeof( lFlagTrue ) );

      /*
      ** Bind the server to PORT, which the client knows
      */

      if ( bind( lSockFd, ( struct sockaddr * ) & sSrvrAddr, sizeof( sSrvrAddr ) ) == OE_ERROR )
      {
         /*
         ** If we can't bind, no one can conect, fatal out
         */

         GS_LogEvent( EN_BIND_ERR,
                      OE_SOCKET_ERRNO,
                      0,
                      FATAL );
         GS_DeleteTask( 0 );
      }


      /*
      ** Now note the socket in the multicast connections table
      */

      for ( iConnIndex = iIndex * IP_MAX_MEMBERSHIPS;
            iConnIndex < ( iIndex + 1 ) * IP_MAX_MEMBERSHIPS;
            iConnIndex++ )
      {
         sMulticastTbl[ iConnIndex ].iSocket = lSockFd;
      } /* End for connections in sMulticastTbl */
   }  /* End for iMulticastSockets */
#else
   /*
   ** Operating system does not limit the number of multicast connections per
   ** socket, so get a socket, then set all of the socket table entries to the socket.
   */

   /*
   ** Need a socket to do anything, fatal if can't get one....
   */

   if ( ( lSockFd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == OE_ERROR )
   {
      GS_LogEvent( EN_SOCKET_ERR,
                   OE_SOCKET_ERRNO,
                   0,
                   FATAL );
      GS_DeleteTask( 0 );
   }


   if ( bind( lSockFd, ( struct sockaddr * ) & sSrvrAddr, sizeof( sSrvrAddr ) ) == OE_ERROR )
   {
      /*
      ** If we can't bind, no one can conect, fatal out
      */

      GS_LogEvent( EN_BIND_ERR,
                   OE_SOCKET_ERRNO,
                   0,
                   FATAL );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -