Knowledge Base Nr: 00322 orasock.cpp - http://www.swe-kaiser.de
Downloads:
linux: oracle: pl/sql: c-interface für socket-kommunikation
//################### c-header:
extern "C"
{
//kommunikation - initialisieren
// parameter:
// lpszIP: ip-adresse elagerät als string z.b.: "192.168.20.88"
// nPort: portnummer (default: 60000)
// rückgabewert:
// 0: ok
// -1: socket noch offen - falsche aufrufreihenfolge
// -2: keine verbindung
int slopen(const char* lpszIP, int nPort);
//kommunikation - befehl ausführen
// parameter:
// lpszRequest: befehlsstring von pc an ela - z.b. "CAL"
// szAnswer: antwort von ela ann pc oder fehlertext
// rückgabewert:
// 0: ok
// -1: socket nicht offen - falsche aufrufreihenfolge
// -2: schreibfehler - fehlertext in szAnswer
// -3: lesefehler - fehlertext in szAnswer
int slsend(const char* lpszRequest, char* szAnswer);
//kommunikation - beenden
// rückgabewert:
// immer 0: ok
int slclose();
}
//################### c-source:
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "socklib.h"
const int SOCK_DELAY = 250 * 1000;
static int g_sock = 0;
int slopen(const char* lpszIP, int nPort)
{
if (g_sock) //socket noch offen - falsche aufrufreihenfolge?
return -1;
struct sockaddr_in adr_serv;
// g_sock = socket(PF_INET, SOCK_DGRAM, 0);
g_sock = socket(PF_INET, SOCK_STREAM, 0);
memset(&adr_serv, 0, sizeof(adr_serv));
adr_serv.sin_family = AF_INET;
adr_serv.sin_port = htons(nPort);
adr_serv.sin_addr.s_addr = inet_addr(lpszIP); //g_params.strPortMegamat);
bool bSucc = connect(g_sock, (struct sockaddr*)&adr_serv, sizeof(adr_serv)) >= 0;
if (!bSucc)
return -2;
return 0;
}
int slsend(const char* lpszRequest, char* szAnswer)
{
if (!g_sock)
{
strcpy(szAnswer, "ERROR: slopen() nicht aufgerufen!");
return -1;
}
int nWritten = 0; int nRead = 0;
char rbuf[100] = {0};
nWritten = write(g_sock, lpszRequest, strlen(lpszRequest));
if (nWritten <= 0)
{
sprintf(szAnswer, "ERROR: schreibfehler %d - %s! ", nWritten, strerror(errno));
return -2;
}
usleep(SOCK_DELAY);
nRead = read(g_sock, rbuf, sizeof(rbuf));
if (nRead <= 0)
{
sprintf(szAnswer, "ERROR: lesefehler %d - %s! ", nRead, strerror(errno));
return -3;
}
rbuf[nRead] = 0;
strcpy(szAnswer, rbuf);
return 0;
}
int slclose()
{
close(g_sock);
g_sock = 0;
return 0;
}
//################# c-test-programm:
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <string.h>
#include "socklib.h"
//////////////////main/////////////////////////////////////////
const char* ELAIP = "192.168.20.xxx";
const int ELAPORT = 60000;
int main(int argc, char *argv[])
{
printf("*** socklib Test (mit ^c - abbrechen) ***\r\n"); fflush(stdout);
for (int n=0; n<argc; n++)
printf(" arg(%d): <%s>\r\n", n, argv[n]); fflush(stdout);
char szELATELE[1000] = "X01D01:CAL@\r\n";
if (argc>1)
{
for (int n=0; n<argc; n++)
{
if (n==1)
sprintf(szELATELE, "X01D01:%s", argv[1]);
else
{
strcat(szELATELE, "\n");
strcat(szELATELE, argv[n]);
}
}
strcat(szELATELE, "@\r\n");
}
int nErr = 0;
char szRecv[1000] = {0};
nErr = slopen(ELAIP, ELAPORT);
printf("*** slopen(): err:%d <%s,%d>\r\n", nErr, ELAIP, ELAPORT); fflush(stdout);
if (nErr)
printf("*** slopen(): <%s>\r\n", strerror(errno));
nErr = slsend(szELATELE, szRecv);
printf("*** slsend() err:%d <%s>\r\n", nErr, strerror(errno)); fflush(stdout);
printf("*** slsend() send: <%s>\r\n", szELATELE); fflush(stdout);
printf("*** slsend() recv: <%s>\r\n", szRecv); fflush(stdout);
nErr = slclose();
printf("*** slclose(): err:%d\r\n", nErr); fflush(stdout);
printf("*** Ende\r\n"); fflush(stdout);
return EXIT_SUCCESS;
}
//############### package socklib
PACKAGE SockLib IS
/*--------------------------------------------------------------*\
* generelle Socket Kommunikationsbibliothek für ELA
////////////////// c-interface für kommunikation zwischen ela und pc
//
//source, doku und binaries: //dslxs02/netclients/common/socklib
//test.sh: schickt commandos an ela
\*--------------------------------------------------------------*/
/*--------------------------------------------------------------*\
* FUNCTION slopen()
//kommunikation - initialisieren
// parameter:
// lpszIP: ip-adresse elagerät als string z.b.: "192.168.20.88"
// nPort: portnummer (default: 60000)
// rückgabewert:
// 0: ok
// -1: socket noch offen - falsche aufrufreihenfolge
// -2: keine verbindung
\*--------------------------------------------------------------*/
FUNCTION slopen(
lpszIP IN VARCHAR2,
nPort IN PLS_INTEGER
) RETURN PLS_INTEGER;
/*--------------------------------------------------------------*\
* FUNCTION slclose()
//kommunikation - beenden
// rückgabewert:
// immer 0: ok
\*--------------------------------------------------------------*/
FUNCTION slclose() RETURN PLS_INTEGER;
/*--------------------------------------------------------------*\
* FUNCTION slsend():
//kommunikation - befehl ausführen
// parameter:
// lpszRequest: befehlsstring von pc an ela - z.b. "CAL"
// szAnswer: antwort von ela ann pc oder fehlertext
// rückgabewert:
// 0: ok
// -1: socket nicht offen - falsche aufrufreihenfolge
// -2: schreibfehler - fehlertext in szAnswer
// -3: lesefehler - fehlertext in szAnswer
\*--------------------------------------------------------------*/
FUNCTION slsend(
lpszRequest IN VARCHAR2,
szAnswer IN OUT VARCHAR2
) RETURN PLS_INTEGER;
/*--------------------------------------------------------------*\
* The following variables form part of the standard FFIGEN
* error handling routine. The Error Boolean is set to
* indicate that an error has occurred and the varchar2
* variable holds the text of the error.
\*--------------------------------------------------------------*/
FFI_Error BOOLEAN;
FFI_Error_Text VARCHAR2(2000);
FFI_Error_Code NUMBER;
END SockLib;
//############### package body socklib
PACKAGE BODY SockLib IS
-- Private Package Variables
lh_SockLib ORA_FFI.LIBHANDLETYPE;
fh_slopen ORA_FFI.FUNCHANDLETYPE;
fh_slclose ORA_FFI.FUNCHANDLETYPE;
fh_slsend ORA_FFI.FUNCHANDLETYPE;
-- Private PU Declarations
PROCEDURE LoadLibrary;
FUNCTION i_slopen(
FunctionHandle IN ORA_FFI.FUNCHANDLETYPE,
lpszIP IN VARCHAR2,
nPort IN PLS_INTEGER
) RETURN PLS_INTEGER;
PROCEDURE rg_slopen;
FUNCTION i_slclose(
FunctionHandle IN ORA_FFI.FUNCHANDLETYPE,
) RETURN PLS_INTEGER;
PROCEDURE rg_slclose;
FUNCTION i_slsend(
FunctionHandle IN ORA_FFI.FUNCHANDLETYPE,
lpszRequest IN VARCHAR2,
szAnswer IN OUT VARCHAR2
) RETURN PLS_INTEGER;
PROCEDURE rg_slsend;
-- Pragma statements which Hook the PL/SQL into the 3gl Function Call
-- *** Do Not Alter These Statements ***
PRAGMA INTERFACE(C,i_slopen, 11265);
PRAGMA INTERFACE(C,i_slclose, 11265);
PRAGMA INTERFACE(C,i_slsend, 11265);
l
-- Bodies for Private PUs
/*--------------------------------------------------------------*\
* The LoadLibrary procedure attempts to load the specified
* 3gl library file so the the functions within it can be
* accessed. It first of all checks to see if the Library
* file is loaded already, and if it isn't does the load.
\*--------------------------------------------------------------*/
PROCEDURE LoadLibrary IS
BEGIN
BEGIN
lh_SockLib := ORA_FFI.FIND_LIBRARY('/usr/local/lib/socklib.so.1.0.1');
EXCEPTION
WHEN ORA_FFI.FFI_ERROR THEN
lh_SockLib := ORA_FFI.LOAD_LIBRARY(NULL,'/usr/local/lib/socklib.so.1.0.1');
END;
EXCEPTION
WHEN OTHERS THEN
-- Place the first error on the TOOL_ERR stack into the package header variables available for it.
FFI_ERROR := TRUE;
FFI_Error_Text := TOOL_ERR.MESSAGE;
FFI_Error_Code := TOOL_ERR.CODE;
FOR iErrors IN 1..TOOL_ERR.NERRORS LOOP
Message('SockLib: '||TOOL_ERR.MESSAGE);
TOOL_ERR.POP;
END LOOP;
TOOL_ERR.CLEAR;
END LoadLibrary;
PROCEDURE rg_slopen IS
BEGIN
fh_slopen := ORA_FFI.REGISTER_FUNCTION(lh_SockLib,'slopen',ORA_FFI.C_STD);
ORA_FFI.REGISTER_PARAMETER(fh_slopen,ORA_FFI.C_CHAR_PTR);
ORA_FFI.REGISTER_PARAMETER(fh_slopen,ORA_FFI.C_INT);
ORA_FFI.REGISTER_RETURN(fh_slopen,ORA_FFI.C_INT);
EXCEPTION
WHEN OTHERS THEN
-- Place the first error on the TOOL_ERR stack into the package header variables available for it.
FFI_ERROR := TRUE;
FFI_Error_Text := TOOL_ERR.MESSAGE;
FFI_Error_Code := TOOL_ERR.CODE;
FOR iErrors IN 1..TOOL_ERR.NERRORS LOOP
Message('SockLib: '||TOOL_ERR.MESSAGE);
TOOL_ERR.POP;
END LOOP;
TOOL_ERR.CLEAR;
END rg_slopen;
PROCEDURE rg_slclose IS
BEGIN
fh_slclose := ORA_FFI.REGISTER_FUNCTION(lh_SockLib,'slclose',ORA_FFI.C_STD);
ORA_FFI.REGISTER_RETURN(fh_slclose,ORA_FFI.C_INT);
EXCEPTION
WHEN OTHERS THEN
-- Place the first error on the TOOL_ERR stack into the package header variables available for it.
FFI_ERROR := TRUE;
FFI_Error_Text := TOOL_ERR.MESSAGE;
FFI_Error_Code := TOOL_ERR.CODE;
FOR iErrors IN 1..TOOL_ERR.NERRORS LOOP
Message('SockLib: '||TOOL_ERR.MESSAGE);
TOOL_ERR.POP;
END LOOP;
TOOL_ERR.CLEAR;
END rg_slclose;
PROCEDURE rg_slsend IS
BEGIN
fh_slsend := ORA_FFI.REGISTER_FUNCTION(lh_SockLib,'slsend',ORA_FFI.C_STD);
ORA_FFI.REGISTER_PARAMETER(fh_slsend,ORA_FFI.C_CHAR_PTR);
ORA_FFI.REGISTER_PARAMETER(fh_slsend,ORA_FFI.C_CHAR_PTR);
ORA_FFI.REGISTER_RETURN(fh_slsend,ORA_FFI.C_INT);
EXCEPTION
WHEN OTHERS THEN
-- Place the first error on the TOOL_ERR stack into the package header variables available for it.
FFI_ERROR := TRUE;
FFI_Error_Text := TOOL_ERR.MESSAGE;
FFI_Error_Code := TOOL_ERR.CODE;
FOR iErrors IN 1..TOOL_ERR.NERRORS LOOP
Message('SockLib: '||TOOL_ERR.MESSAGE);
TOOL_ERR.POP;
END LOOP;
TOOL_ERR.CLEAR;
END rg_slsend;
-- Bodies for Public PUs
FUNCTION slopen(
lpszIP IN VARCHAR2,
nPort IN PLS_INTEGER,
) RETURN PLS_INTEGER IS
RC PLS_INTEGER;
l_lpszIP VARCHAR2(256) := lpszIP;
l_nPort PLS_INTEGER := nPort;
BEGIN
rc := i_slopen(
fh_slopen,
l_lpszIP,
l_nPort);
RETURN RC;
END slopen;
FUNCTION slclose(
) RETURN PLS_INTEGER IS
RC PLS_INTEGER;
BEGIN
rc := i_slclose();
RETURN RC;
END slclose;
FUNCTION slsend(
lpszRequest IN VARCHAR2,
szAnswer IN OUT VARCHAR2
) RETURN PLS_INTEGER IS
RC PLS_INTEGER;
l_lpszRequest VARCHAR2(256) := lpszRequest;
l_szAnswer VARCHAR2(256) := szAnswer;
BEGIN
rc := i_slsend(
fh_slsend,
l_lpszRequest,
l_szAnswer);
szAnswer := l_szAnswer;
RETURN RC;
END slsend;
BEGIN
LoadLibrary;
rg_slopen;
rg_slclose;
rg_slsend;
END SockLib;