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

📄 en_sock.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 5 页
字号:

   /*
   ** Initialize  network storage
   */

   en_cd_InitTargetData( );

#if EN_MAX_OUTGOING_CONNECTIONS

	sSeed.pRoutine = ( OE_pTaskFuncType ) en_cd_MngOutgoingEncapTask;
	sSeed.pParameter = NULL;
	sSeed.pStack = NULL;
	sSeed.iStackSize = EP_MNG_OUTGOING_STACK_SIZE;
	sSeed.nPrio = ENCAP_MNG_TASK_PRIO;
	sSeed.pTaskName = "ENCAPMng";
	lTaskID = GS_NewTask( &sSeed );

#endif

   sSeed.pRoutine = ( OE_pTaskFuncType ) en_cd_UDPRecvTask;
   sSeed.pParameter = NULL;
   sSeed.pStack = NULL;
   sSeed.iStackSize = EN_SOCKET_STACK_SIZE;
   sSeed.nPrio = UDP_RECV_TASK_PRIO;
   sSeed.pTaskName = "IRUDP";
   lTaskID = GS_NewTask( &sSeed );

   sSeed.pRoutine = ( OE_pTaskFuncType ) en_cd_Class1RecvTask;
   sSeed.pParameter = NULL;
   sSeed.pStack = NULL;
   sSeed.iStackSize = EN_SOCKET_STACK_SIZE;
   sSeed.nPrio = CLASS1_RECV_TASK_PRIO;
   sSeed.pTaskName = "IRCLASS1";
   lTaskID = GS_NewTask( &sSeed );

   lSockFd = en_cd_PostListen( );
   for ( ;; )
   {
      UC_SetMem( ( char * ) &sCli_addr, 0, sizeof( sCli_addr ) );
      sCli_addr.sin_family = AF_INET;
      sCli_addr.sin_addr.s_addr = htonl( INADDR_ANY );  /* accept from anybody */
      sCli_addr.sin_port = htons( 0 );
      lAddrLen = sizeof( sCli_addr );

      /*
      ** Wait for a connect request from the client
      */

#if defined( WIN32 )
      nt_Suspend( );
#endif
      lSockFd2 = accept( lSockFd, ( struct sockaddr * ) & sCli_addr, &lAddrLen );
#if defined( WIN32 )
      nt_Resume( );
#endif
      if ( lSockFd2 == OE_ERROR )
      {
         /*
         ** Perhaps it is just temporary, log the problem, wait to allow us to
         ** catch our breadth and then continue
         */

         GS_LogEvent( EN_ACCEPT_ERR, OE_SOCKET_ERRNO,
                      0,
                      WARNING );
         OE_TaskDelay(  MSEC2TICKS(1000) );   /* One second */
         continue;
      }
    /*
    ** make sure we are within the limits for the number of simultaneous sockets
    */
       if ((EN_MAX_INCOMING_CONNECTIONS <= lECE_connects_in) ||
           (MAX_TCP_SOCKETS <= lECE_connects))
       {
          closesocket(lSockFd2);    /* Close the socket right away, we are up to our limit */
          OE_TaskDelay( MSEC2TICKS(1000) ); /* Delay for 1 second maybe room will become available */
          continue;           /* return to the forever loop */
       }
      /*
      ** Somebody wants to connect to us, give them a server
      ** Create a task to process the request from the client.
      ** Go ahead and wait for further requests
      */

      psEce = GS_Malloc( sizeof( ECE ) );     /* Allocate the endopoint structure */
      UC_SetMem( psEce, 0, sizeof( ECE ) );   /* Zero out all fields */
      psEce->lSockFd = lSockFd2;
      psEce->sEid.u.type = ECE_TYPE_INBOUND;  /* Assign an inbound connection id */
      psEce->lState = ECE_STATE_CONNECTED;    /* We are connected */
      psEce->sEid.u.idx = lSockFd2;           /* Form the handle, idx is socket # */
      psEce->sEid.u.seq = lTotal_lECE_connects; /* Add in the Total # of connections */

#ifndef _WIN32
      psEce->sAddr.sin_len = sizeof( struct sockaddr_in );
#endif
      lAddrLen = sizeof psEce->sAddr;

#if defined( WIN32 )
      nt_Suspend( );
#endif
      nStatus = getpeername( lSockFd2, ( struct sockaddr * ) & psEce->sAddr, ( INT32 * ) & lAddrLen );
#if defined( WIN32 )
      nt_Resume( );
#endif
      if ( nStatus == OE_ERROR )
      {
         /*
         ** Couldn't get the peername we are connected to
         */

         GS_LogEvent( EN_UNKNOWN_HOST,
                      OE_SOCKET_ERRNO,
                      0,
                      TRIVIAL );
      }

      /*
      ** We need to create the message queue so we can pass it to
      ** the send task
      */
      sSendTaskMsgQueue = OE_MsgQCreate( 100,   /* Number of messages, */
                                         sizeof( EnCdMessageType ),
                                         MSG_Q_PRIORITY );

      /*
      ** Could not create the send queue for the send/recv pair. Log it but
      ** warn only.  There may be other connections still active and fully
      ** functional
      */

      if ( sSendTaskMsgQueue == 0 )
      {
         /*
         ** Close the socket. Queue creation failed, no use going on
         */

         GS_LogEvent( EN_QUEUE_CR_ERR,
                      OE_SOCKET_ERRNO,
                      0,
                      WARNING );
         closesocket( lSockFd2 );
         continue;
      }
      psEce->sOutputQ = sSendTaskMsgQueue;

      sprintf( achTaskName, "IR%x", sCli_addr.sin_addr.s_addr );

      /*
      ** The receive task will have the lowest priority of all the socket level tasks.
      ** This is to keep the system from bogging down if it is overwhelemed with
      ** packets from outside clients
      */
      sSeed.pRoutine = ( OE_pTaskFuncType ) en_cd_EncapRecvTask;
      sSeed.pParameter = ( void * ) psEce;
      sSeed.pStack = NULL;
      sSeed.iStackSize = EN_SOCKET_STACK_SIZE;
      sSeed.nPrio = IN_RECV_TASK_PRIO;
      sSeed.pTaskName = achTaskName;

      /*
      ** The following create call uses the OE_CreateTask call because it can be deleted.  As of this
      ** writting there is no GS_DeleteTask routine in the GS_Utils library
      */

      lTaskID = OE_CreateTask( &sSeed );
      if ( lTaskID == 0 )
      {
         /*
         ** We could not spawn the task for the inclomming connection request.
         ** We may already have fully functional connections and this is
         ** exceeding a quota of some type.  Warn here, let the other
         ** connections continue operating.
         */

         GS_LogEvent( EN_TASK_SP_ERR,
                     OE_SOCKET_ERRNO,
                     0,
                     WARNING );
         closesocket( lSockFd2 );
         continue;
      }
   }  /* End forever */


}  /* end en_cd_PassiveWaitTask( ) */



/*---------------------------------------------------------------------------
** en_cd_TcpConnect( )
**---------------------------------------------------------------------------
*/

UINT32 en_cd_TcpConnect( struct sockaddr_in * psF_Addr,
                 UINT32 * lSockfd,
                 UINT32 * nErr )
{
   UINT32          lNewSockFd;
    INT32          nStatus = 0;
   UINT32          nHaveFd = OE_ERROR;
   UINT32          lOptSet = 1;
   struct sockaddr_in sCli_addr;
   UINT32          lSize;


   do
   {
      /*
      ** create a socket to use for outgoing connections
      */

      if ( ( lNewSockFd = socket( AF_INET, SOCK_STREAM, 0 ) ) == OE_ERROR )
      {
         nStatus = lNewSockFd;
         break;
      }
      nHaveFd = OK;

      /*
      ** set common socket options.  Should not get any errors at
      ** this point, but check for them anyway.
      */

      lSize = 16384;

      if ( ( nStatus = setsockopt( lNewSockFd,
                                SOL_SOCKET,
                                SO_SNDBUF,
                                ( char * ) &lSize,
                                sizeof( lSize ) ) ) == OE_ERROR )
         break;

      lSize = 16384;

      if ( ( nStatus = setsockopt( lNewSockFd,
                                SOL_SOCKET,
                                SO_RCVBUF,
                                ( char * ) &lSize,
                                sizeof( lSize ) ) ) == OE_ERROR )
         break;

      if ( ( nStatus = setsockopt( lNewSockFd,
                                SOL_SOCKET,
                                SO_KEEPALIVE,
                                ( char * ) &lOptSet,
                                sizeof( lOptSet ) ) ) == OE_ERROR )
         break;

      if ( ( nStatus = setsockopt( lNewSockFd,
                                IPPROTO_TCP,
                                TCP_NODELAY,
                                ( char * ) &lOptSet,
                                sizeof( lOptSet ) ) ) == OE_ERROR )

      UC_SetMem( ( char * ) &sCli_addr, 0, sizeof( sCli_addr ) );
      sCli_addr.sin_family = AF_INET;
      sCli_addr.sin_port = htons( 0 );
      sCli_addr.sin_addr.s_addr = htonl( INADDR_ANY );

      if ( bind( lNewSockFd, ( struct sockaddr * ) & sCli_addr, sizeof( sCli_addr ) ) == OE_ERROR ){
         DBLN( "bind()==OE_ERROR" );
         break;
      }

      /*
      ** Initiate a connection to the host
      */

#if defined( WIN32 )
      nt_Suspend( );
#endif
      nStatus = connect( lNewSockFd, ( struct sockaddr * ) psF_Addr, sizeof( *psF_Addr ) );
#if defined( WIN32 )
      nt_Resume( );
#endif
      if( nStatus == OE_ERROR )
      {
         /*
         ** Something happened.  Could be that the host we were going to
         ** connect to shut down. This should not be a fatal error as it might
         ** not be our fault
         */

         GS_LogEvent( EN_CONNECT_ERR,
                     OE_SOCKET_ERRNO,
                     0,
                     WARNING );
         break;
      }
   } while ( 0 );

   if ( nStatus == OE_ERROR )
   {
      if ( nHaveFd == OK )
         closesocket( lNewSockFd );
      *nErr = OE_SOCKET_ERRNO;
      return ( OE_ERROR );
   }
   else
   {
      *lSockfd = lNewSockFd;
      return ( OK );
   }

}  /* end en_cd_TcpConnect( ) */



/*---------------------------------------------------------------------------
** en_cd_UDPSend( )
**---------------------------------------------------------------------------
*/

UINT32 en_cd_UDPSend( UINT32 fd,
              SOCK_WDESC * psWriteDesc,
              UINT32 flags,
              struct sockaddr_in * to,
              UINT32 * pnErr )
{
   struct msghdr   psWriteMsg;
    INT32          nBytes;


   UC_SetMem( ( caddr_t ) &psWriteMsg, 0, sizeof( psWriteMsg ) );
   psWriteMsg.msg_iov = psWriteDesc->psW_iov;
   psWriteMsg.msg_iovlen = psWriteDesc->lW_iovlen;
   if ( to )
   {
      psWriteMsg.msg_name = ( caddr_t ) to;
      psWriteMsg.msg_namelen = sizeof( *to );
   }

   if ( ( nBytes = sendmsg( fd, &psWriteMsg, flags ) ) == OE_ERROR )
   {
      *pnErr = nBytes; /* !!! !!! !!! nBytes is always OE_ERROR */
      return ( OE_ERROR );
   }
   else
   {
      return ( OK );
   }

}  /* end en_cd_UDPSend( ) */


/*---------------------------------------------------------------------------
** en_cd_UDPEncapSendTask( )
**---------------------------------------------------------------------------
*/

TASKRETURN en_cd_UDPEncapSendTask( TASKPARAM )
{
   EnCdMessageType EnCdMessage;
   UINT32          nShutdown = FALSE;
   OE_Q_ID            sSendTaskMsgQueue;
   UINT32          lSid = 0;
   UINT32          lSockFd;
   UINT32          nStatus;
   SOCK_WDESC      sWriteDesc;


   lSockFd = sUDPEce.lSockFd;
   sSendTaskMsgQueue = sUDPEce.sOutputQ;
   while ( 1 )
   {
      nStatus = OE_MsgQReceive( sSendTaskMsgQueue,   /* Queue to wait at */
                              ( char * ) &EnCdMessage,
                              sizeof EnCdMessage,   /* Size */
                              WAIT_FOREVER );       /* Wait forever */

      switch ( EnCdMessage.Command )
      {

      /*
      ** Encap Message to send. SENDCOMMBUF same but at end we need to
      ** dipose of combuffer
      */

      case SENDINCORPMESSAGE:
      case SENDCOMMBUF:

         if ( EnCdMessage.PacketBuf != NULL )
         {
            /*
            ** Form the iov's for sendmessage
            */

            en_cd_FormatIOV( EnCdMessage.PacketBuf, &sWriteDesc );

            /*
            ** Write to the socket.  Check for a possible
            ** error. Close down the connection if the
            ** error is not one of the flow control
            ** errors.
            **
            ** Packets are sent in there entirety, no need to loop until
            ** complete message sent
            */
            if ( en_cd_UDPSend( lSockFd, &sWriteDesc, 0, &EnCdMessage.PacketBuf->sEce.sAddr, &nStatus ) == OE_ERROR )
            {
               if ( ( nStatus != EWOULDBLOCK ) && ( nStatus != ENOBUFS ) )
               {
                  /* Nothing we can do about errors, ignore them */
               }
            }

⌨️ 快捷键说明

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