📄 o22siost.cpp
字号:
//-----------------------------------------------------------------------------//// O22SIOST.cpp// Copyright (c) 2000-2002 by Opto 22//// Source for the O22SnapIoStream C++ class. // // The O22SnapIoStream C++ class is used to listen to UDP stream packets// from an Opto 22 SNAP Ethernet I/O unit.//// See the header file for more information on using this class.//// While this code was developed on Microsoft Windows 32-bit operating // systems, it is intended to be as generic as possible. For Windows specific// code, search for "_WIN32" and "_WIN32_WCE". For Linux specific code, search// for "_LINUX".//-----------------------------------------------------------------------------#ifndef __O22SIOST_H_#include "O22SIOST.h"#endif//added by added for vxworks #include "VxWorks.h"#include "sockLib.h"#include "inetLib.h"#include "stdioLib.h"#include "strLib.h"#include "ioLib.h"#include "fioLib.h"#include "pthread.h"#include "taskLib.h"#include <time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include "stdio.h"#include "D:/tornado2.2/host/diab/include/sys/times.h"typedef int socklen_t; #ifdef _VxWorkstypedef int ssize_t; typedef int SOCKET; typedef unsigned char BYTE; typedef unsigned long DWORD; #define FALSE 0 #define SOCKET_ERROR (-1) //end added #endif //gy changed for test 5.30#ifdef _WIN32#define WINSOCK_VERSION_REQUIRED_MAJ 2#define WINSOCK_VERSION_REQUIRED_MIN 0#endif#ifdef _WIN32void StreamThread(void * pParam);#endif//#ifdef _LINUXvoid * StreamThread(void * pParam);//#endif//gy changed for vxworks O22SnapIoStream::O22SnapIoStream()//-------------------------------------------------------------------------------------------------// Constructor//-------------------------------------------------------------------------------------------------{ // Set defaults nStreamListCount = 0; pStreamList = NULL; m_pbyLastStreamBlock = NULL; m_StreamSocket = INVALID_SOCKET; m_nStreamType = 0; // The type set in OpenStreaming() m_nStreamLength = 0; // The length set in OpenStreaming() m_bListenToStreaming = FALSE; memset(&m_LastStreamBlock, 0, sizeof(SIOMM_StreamCustomBlock)); // Structure containing the last stream#ifdef _WIN32 m_hStreamThread = NULL; InitializeCriticalSection(&m_StreamCriticalSection);#endif//#ifdef _LINUX memset(&m_hStreamThread, 0, sizeof(pthread_t)); // Handle to the stream listening thread pthread_mutex_init(&m_StreamCriticalSection, NULL);//#endif} O22SnapIoStream::~O22SnapIoStream()//-------------------------------------------------------------------------------------------------// Destructor//-------------------------------------------------------------------------------------------------{#ifdef _WIN32 WSACleanup();#endif#ifdef _WIN32 DeleteCriticalSection(&m_StreamCriticalSection);#endif//#ifdef _LINUX pthread_mutex_destroy(&m_StreamCriticalSection);//#endif}LONG O22SnapIoStream::OpenStreaming(long nType, long nLength, long nPort)//-------------------------------------------------------------------------------------------------// Prepares to start listening for stream packets from SNAP Ethernet I/O units.//// nType can be either of the following values:// #define SIOMM_STREAM_TYPE_STANDARD 1// #define SIOMM_STREAM_TYPE_CUSTOM 2//// Standard means that default streaming is being sent from the I/O units.// Custom means that a custom memory map area and length is being streamed from the I/O unit.// This class expects for all I/O units to be streaming the same type and length.//-------------------------------------------------------------------------------------------------{ int nResult; // for checking the return values of functions#ifdef _WIN32 // Initialize WinSock.dll WSADATA wsaData; // for checking WinSock nResult = WSAStartup( O22MAKEWORD( WINSOCK_VERSION_REQUIRED_MIN, WINSOCK_VERSION_REQUIRED_MAJ ), &wsaData ); if ( nResult != 0 ) { // We couldn't find a socket interface. return SIOMM_ERROR_NO_SOCKETS; } // Confirm that the WinSock DLL supports WINSOCK_VERSION if (( O22LOBYTE( wsaData.wVersion ) != WINSOCK_VERSION_REQUIRED_MAJ) || ( O22HIBYTE( wsaData.wVersion ) != WINSOCK_VERSION_REQUIRED_MIN)) { // We couldn't find an acceptable socket interface. WSACleanup( ); return SIOMM_ERROR_NO_SOCKETS; } #endif // If a socket is open, close it now. CloseStreaming(); // Set the listen flag m_bListenToStreaming = TRUE; // Check the stream type and make sure we know about it if (SIOMM_STREAM_TYPE_STANDARD == nType) { m_nStreamType = nType; m_nStreamLength = sizeof(SIOMM_StreamStandardBlock) - 4; } else if (SIOMM_STREAM_TYPE_CUSTOM == nType) { m_nStreamType = nType; m_nStreamLength = nLength + 8; // plus 4 for the header and 4 for the mem-map address } else { return SIOMM_ERROR_STREAM_TYPE_BAD; } // Allocate the response buffer m_pbyLastStreamBlock = new BYTE[m_nStreamLength]; if (m_pbyLastStreamBlock == NULL) return SIOMM_ERROR_OUT_OF_MEMORY; // Couldn't allocate memory! // Create the UDP socket m_StreamSocket = socket(AF_INET, SOCK_DGRAM, 0); if (m_StreamSocket == INVALID_SOCKET) { // Couldn't create the socket#ifdef _WIN32 WSACleanup( );#endif return SIOMM_ERROR_CREATING_SOCKET; } // Make the socket non-blocking#ifdef _WIN32 // Windows uses ioctlsocket() to set the socket as non-blocking. // Other systems may use ioctl() or fcntl() unsigned long nNonBlocking = 1; if (SOCKET_ERROR == ioctlsocket(m_StreamSocket, FIONBIO, &nNonBlocking))#endif#ifdef _LINUX if (-1 == fcntl(m_StreamSocket,F_SETFL,O_NONBLOCK))#endifif((socket (AF_INET,SOCK_DGRAM,0))==ERROR)//gy added for vxworks 5.29 { CloseStreaming(); return SIOMM_ERROR_CREATING_SOCKET; } // Setup the socket address structure sockaddr_in StreamSocketAddress; StreamSocketAddress.sin_addr.s_addr = INADDR_ANY; StreamSocketAddress.sin_family = AF_INET; StreamSocketAddress.sin_port = htons((WORD)nPort); // attempt connection nResult = bind(m_StreamSocket, (sockaddr*) &StreamSocketAddress, sizeof(StreamSocketAddress));#ifdef _WIN32 if (SOCKET_ERROR == nResult) { nResult = WSAGetLastError(); // for checking the specific error for debugging purposes }#endif // Create the listener thread#ifdef _WIN32 m_hStreamThread = _beginthread(StreamThread, 0, this /*param*/); // Check for error if (-1 == m_hStreamThread) { m_hStreamThread = 0; return SIOMM_ERROR; }#endif//#ifdef _LINUX if (0 != pthread_create(&m_hStreamThread, NULL, StreamThread, this)) { m_hStreamThread = 0; return SIOMM_ERROR; }//#endif return SIOMM_OK;}LONG O22SnapIoStream::CloseStreaming()//-------------------------------------------------------------------------------------------------// Stops all listening and cleans everything up.//-------------------------------------------------------------------------------------------------{ // Close up everything if (m_StreamSocket != INVALID_SOCKET) { #ifdef _WIN32 closesocket(m_StreamSocket);#endif//#ifdef _LINUX close(m_StreamSocket);//#endif }#ifdef _WIN32 EnterCriticalSection(&m_StreamCriticalSection);#endif//#ifdef _LINUX pthread_mutex_lock(&m_StreamCriticalSection);//#endif O22StreamItem * pTempStreamItem; O22StreamItem * pTempNextStreamItem; pTempNextStreamItem = pStreamList; while (pTempNextStreamItem != NULL) {// in_addr in;// in.S_un.S_addr = pTempNextStreamItem->nIpAddress;// StopStreamListening(inet_ntoa(in));// I don't think this while loop is neccessary. The client will have// to stop all of its listening before attemping to close.// Or, this section needs more work. The VB client dies when // CloseStreaming() is called with open listeners. pTempStreamItem = pTempNextStreamItem; pTempNextStreamItem = pTempStreamItem->pNext; delete pTempStreamItem; nStreamListCount--; } pStreamList = NULL;#ifdef _WIN32 LeaveCriticalSection(&m_StreamCriticalSection);#endif//#ifdef _LINUX pthread_mutex_unlock(&m_StreamCriticalSection);//#endif // Clean up and reset the stream data block. if (m_pbyLastStreamBlock) { delete [] m_pbyLastStreamBlock; m_pbyLastStreamBlock = NULL; } // Stop listening for packets by setting this flag. It will cause the listening thread to stop. m_bListenToStreaming = FALSE; return SIOMM_OK;}#ifdef _WIN32void StreamThread(void * pParam)#endif//#ifdef _LINUXvoid * StreamThread(void * pParam)//#endif//gy changed 5.28//-------------------------------------------------------------------------------------------------// This is THE second thread that does the listening.//-------------------------------------------------------------------------------------------------{ O22SnapIoStream * pThis = (O22SnapIoStream*) pParam; // Call the initilization function if (pThis->m_pStartThreadCallbackFunc) pThis->m_pStartThreadCallbackFunc(pThis->m_pStartThreadParam); // Enter a loop. We'll break out when done. while (1) { long nResult; // Call StreamHandler(), the main worker function of this thread nResult = pThis->StreamHandler(); // Check for error. Timeout errors are okay in this instance. if (!((SIOMM_OK == nResult) || (SIOMM_TIME_OUT == nResult))) { break; } // Check flag to see if we should keep looping if (!pThis->m_bListenToStreaming) { // Stop looping nResult = SIOMM_OK; break; } // Check the timeouts of all stream items pThis->CheckStreamTimeouts();#ifdef _WIN32 Sleep(1);#endif//#ifdef _LINUX // usleep(1000); taskDelay (1);//gy added for vxworks 5.29//#endif } // Call the shutdown callback function if (pThis->m_pStopThreadCallbackFunc) pThis->m_pStopThreadCallbackFunc(pThis->m_pStopThreadParam); // End this thread#ifdef _WIN32 _endthread(); return;#endif//#ifdef _LINUX pthread_exit(NULL); return NULL;//#endif}LONG O22SnapIoStream::CheckStreamTimeouts()//-------------------------------------------------------------------------------------------------// Checks if any stream items have timed out//-------------------------------------------------------------------------------------------------{ O22StreamItem * pTempStreamItem; pTempStreamItem = pStreamList; DWORD nTickCount;#ifdef _WIN32 EnterCriticalSection(&m_StreamCriticalSection);#endif//#ifdef _LINUX pthread_mutex_lock(&m_StreamCriticalSection);//#endif // Get the tick count#ifdef _WIN32 nTickCount = GetTickCount(); // GetTickCount returns the number of milliseconds that have // elapsed since the system was started.#endif#ifdef _LINUX tms DummyTime; nTickCount = times(&DummyTime); // times() returns the number of milliseconds that have // elapsed since the system was started.#endif long nTemp = 0; // for counting through the list of stream items. // Loop through the list of stream items while (pTempStreamItem != NULL) { // Increment the count nTemp++; // Double check we haven't gone off the end of the list if (nTemp > nStreamListCount) { break; } // No need to check if a timeout has already been sent. if (!pTempStreamItem->bTimeoutSent) { // Do the timeout math! if ((nTickCount - pTempStreamItem->nLastPacketTickCount) > pTempStreamItem->nTimeout)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -