Show TOC

Background documentationRFC Server Programming Example Locate this document in the navigation structure

 

In the following section you can find a programming example using basic elements of RFC Server programs such as registering the server, installing a server function, and error handling:

#include <stdlib.h>

#include <stdio.h>

#include "sapnwrfc.h"

static int listening = 1;

/*

Transaction SE37 in the AS ABAP does not yet allow you to set complex inputs, so in order to test

this example, you will probably need to write a short ABAP report, which sets a few

input lines for IMPORT_TAB and then does a

Syntax Syntax

  1. CALL FUNCTION 'STFC_DEEP_TABLE' DESTINATION 'MY_SERVER'
  2.   EXPORTING
  3.     import_tab       = imtab
  4.   IMPORTING
  5.     export_tab       = extab
  6.     resptext         = text
  7.   EXCEPTIONS
  8.     system_failure   = 1  MESSAGE mes.
End of the code.

This also allows you to catch the detailed texts for SYSTEM_FAILURES.

Note: STFC_DEEP_TABLE only exists as of SAP_BASIS Release 6.20.

Syntax Syntax

  1. void errorHandling(RFC_RC rc, SAP_UC description[], RFC_ERROR_INFO* errorInfo, RFC_CONNECTION_HANDLE connection){
  2. 	printfU(cU("%s: %d\n"), description, rc);
  3. 	printfU(cU("%s: %s\n"), errorInfo->key, errorInfo->message);
  4. 	// It's better to close the TCP/IP connection cleanly, than to just let the
  5. 	// backend get a "Connection reset by peer" error...
  6. 	if (connection != NULL) RfcCloseConnection(connection, errorInfo);
  7. 	exit(1);
  8. }
  9. RFC_RC SAP_API stfcDeepTableImplementation(RFC_CONNECTION_HANDLE rfcHandle, RFC_FUNCTION_HANDLE funcHandle, RFC_ERROR_INFO* errorInfoP){
  10. 	RFC_ATTRIBUTES attributes;
  11. 	RFC_TABLE_HANDLE importTab = 0;
  12. 	RFC_STRUCTURE_HANDLE tabLine = 0;
  13. 	RFC_TABLE_HANDLE exportTab = 0;
  14. 	RFC_ERROR_INFO errorInfo ;
  15. 	RFC_CHAR buffer[257]; //One for the terminating zero
  16. 	RFC_INT intValue;
  17. 	RFC_RC rc;
  18. 	unsigned tabLen = 0, strLen;
  19. 	unsigned  i = 0;
  20. 	buffer[256] = 0;
  21. 	printfU(cU("\n*** Got request for STFC_DEEP_TABLE from the following system: ***\n"));
  22. /*If you want to include an authorization check for your RFC server according to SAP Note 1058327, insert it now:*/
  23. 	RfcGetConnectionAttributes(rfcHandle, , );
  24. 	printfU(cU("System ID: %s\n"), attributes.sysId);
  25. 	printfU(cU("System No: %s\n"), attributes.sysNumber);
  26. 	printfU(cU("Mandant  : %s\n"), attributes.client);
  27. 	printfU(cU("Host     : %s\n"), attributes.partnerHost);
  28. 	printfU(cU("User     : %s\n"), attributes.user);
  29. 	//Print the Importing Parameter
  30. 	printfU(cU("\nImporting Parameter:\n"));
  31. 	RfcGetTable(funcHandle, cU("IMPORT_TAB"), , );
  32. 	RfcGetRowCount(importTab, , );
  33. 	printfU(cU("IMPORT_TAB (%d lines)\n"), tabLen);
  34. 	for (i=0; i<tabLen; i++){
  35. 		RfcMoveTo(importTab, i, );
  36. 		printfU(cU("\t\t-line %d\n"), i);
  37. 		RfcGetInt(importTab, cU("I"), , );
  38. 		printfU(cU("\t\t\t-I:\t%d\n"), intValue);
  39. 		RfcGetString(importTab, cU("C"), buffer, 11, , );
  40. 		printfU(cU("\t\t\t-C:\t%s\n"), buffer);
  41. 		// Check for the stop flag:
  42. 		if (i==0 && strncmpU(cU("STOP"), buffer, 4) == 0) listening = 0;
  43. 		RfcGetStringLength(importTab, cU("STR"), , );
  44. 		if (strLen > 256) printfU(cU("STRING length bigger than 256: %d. Omitting the STR field...\n"), strLen);
  45. 		else{
  46. 			RfcGetString(importTab, cU("STR"), buffer, 257, , );
  47. 			printfU(cU("\t\t\t-STR:\t%s\n"), buffer);
  48. 		}
  49. 		RfcGetStringLength(importTab, cU("XSTR"), , );
  50. 		if (strLen > 128) printfU(cU("XSTRING length bigger than 128: %d. Omitting the XSTR field...\n"), strLen);
  51. 		else{
  52. 			RfcGetString(importTab, cU("XSTR"), buffer, 257, , );
  53. 			printfU(cU("\t\t\t-XSTR:\t%s\n"), buffer);
  54. 		}
  55. 	}
  56. 	//Now set the Exporting Parameters
  57. 	printfU(cU("\nSetting values for Exporting Parameters:\n"));
  58. 	printfU(cU("Please enter a value for RESPTEXT:\n> "));
  59. 	getsU(buffer);
  60. 	RfcSetChars(funcHandle, cU("RESPTEXT"), buffer, strlenU(buffer), );
  61. 	printfU(cU("\nPlease enter the number of lines in EXPORT_TAB:\n> ")); 
  62. 	getsU(buffer);
  63. 	tabLen = atoiU(buffer);
  64. 	RfcGetTable(funcHandle, cU("EXPORT_TAB"), , );
  65. 	for (i=0; i<tabLen; i++){
  66. 		tabLine = RfcAppendNewRow(exportTab, );
  67. 		printfU(cU("Line %d\n"), i);
  68. 		printfU(cU("\tPlease enter a value for C [CHAR10]:> "));
  69. 		getsU(buffer);
  70. 		RfcSetChars(tabLine, cU("C"), buffer, strlenU(buffer), );
  71. 		printfU(cU("\tPlease enter a value for I [INT4]:> "));
  72. 		getsU(buffer);
  73. 		RfcSetInt(tabLine, cU("I"), atoiU(buffer), );
  74. 		printfU(cU("\tPlease enter a value for STR [STRING]:> "));
  75. 		fgetsU(buffer, 257, stdin); // For these fields better make sure, the user doesn't bust our buffer...
  76. 		strLen = strlenU(buffer) - 1;
  77. 		// In contrast to gets, fgets includes the linebreak... Very consistent...
  78. 		RfcSetString(tabLine, cU("STR"), buffer, strLen, );
  79. 		mark: printfU(cU("\tPlease enter a value for XSTR [XSTRING]:> "));
  80. 		fgetsU(buffer, 257, stdin);
  81. 		strLen = strlenU(buffer) - 1;
  82. 		// In contrast to gets, fgets includes the linebreak... Very consistent...
  83. 		rc = RfcSetString(tabLine, cU("XSTR"), buffer, strLen, );
  84. 		if (rc != RFC_OK){
  85. 			printfU(cU("\tInvalid value for XSTR. Please only use hex digits 00 - FF.\n"));
  86. 			goto mark;
  87. 		}
  88. 	}
  89. 	printfU(cU("**** Processing of STFC_DEEP_TABLE finished ***\n\n"));
  90. 	return RFC_OK;
  91. }
  92. int mainU(int argc, SAP_UC** argv){
  93. 	RFC_RC rc;
  94. 	RFC_FUNCTION_DESC_HANDLE stfcDeepTableDesc;
  95. 	RFC_CONNECTION_PARAMETER repoCon[8], serverCon[3];
  96. 	RFC_CONNECTION_HANDLE repoHandle, serverHandle;
  97. 	RFC_ERROR_INFO errorInfo;
  98. 	serverCon[0].name = cU("program_id");	serverCon[0].value = cU("MY_SERVER");
  99. 	serverCon[1].name = cU("gwhost");	serverCon[1].value = cU("binmain");
  100. 	serverCon[2].name = cU("gwserv");	serverCon[2].value = cU("sapgw53");
  101. 	repoCon[0].name = cU("client");	repoCon[0].value = cU("000");
  102. 	repoCon[1].name = cU("user");	repoCon[1].value = cU("user");
  103. 	repoCon[2].name = cU("passwd");	repoCon[2].value = cU("****");
  104. 	repoCon[3].name = cU("lang");	repoCon[3].value = cU("DE");
  105. 	repoCon[4].name = cU("ashost");	repoCon[4].value = cU("binmain");
  106. 	repoCon[5].name = cU("sysnr");	repoCon[5].value = cU("53");
  107. 	printfU(cU("Logging in..."));
  108. 	repoHandle = RfcOpenConnection (repoCon, 6, );
  109. 	if (repoHandle == NULL) errorHandling(errorInfo.code, cU("Error in RfcOpenConnection()"), , NULL);
  110. 	printfU(cU(" ...done\n"));
  111. 	printfU(cU("Fetching metadata..."));
  112. 	stfcDeepTableDesc = RfcGetFunctionDesc(repoHandle, cU("STFC_DEEP_TABLE"), );
  113. 	// Note: STFC_DEEP_TABLE exists only from SAP_BASIS release 6.20 on
  114. 	if (stfcDeepTableDesc == NULL) errorHandling(errorInfo.code, cU("Error in Repository Lookup"), , repoHandle);
  115. 	printfU(cU(" ...done\n"));
  116. 	printfU(cU("Logging out..."));
  117. 	RfcCloseConnection(repoHandle, );
  118. 	printfU(cU(" ...done\n"));
  119. 	rc = RfcInstallServerFunction(NULL, stfcDeepTableDesc, stfcDeepTableImplementation, );
  120. 	if (rc != RFC_OK) errorHandling(rc, cU("Error Setting "), , repoHandle);
  121. 	printfU(cU("Registering Server..."));
  122. 	serverHandle = RfcRegisterServer(serverCon, 3, );
  123. 	if (serverHandle == NULL) errorHandling(errorInfo.code, cU("Error Starting RFC Server"), , NULL);
  124. 	printfU(cU(" ...done\n"));
  125. 	printfU(cU("Starting to listen...\n\n"));
  126. 	while(RFC_OK == rc || RFC_RETRY == rc || RFC_ABAP_EXCEPTION == rc){
  127. 		rc = RfcListenAndDispatch(serverHandle, 120, );
  128. 		printfU(cU("RfcListenAndDispatch() returned %s\n"), RfcGetRcAsString(rc));
  129. 		switch (rc){
  130. 			case RFC_RETRY:	// This only notifies us, that no request came in within the timeout period.
  131. 							// We just continue our loop.
  132. 				printfU(cU("No request within 120s.\n"));
  133. 				break;
  134. 			case RFC_ABAP_EXCEPTION:	// Our function module implementation has returned RFC_ABAP_EXCEPTION.
  135. 								// This is equivalent to an ABAP function module throwing an ABAP Exception.
  136. 								// The Exception has been returned to the SAP system and our connection is still open.
  137. 								// So we just loop around.
  138. 				printfU(cU("ABAP_EXCEPTION in implementing function: %s\n"), errorInfo.key);
  139. 				break;
  140. 			case RFC_NOT_FOUND:	// The SAP system tried to invoke a function module, for which we did not supply
  141. 								// an implementation. The SAP system has been notified of this through a SYSTEM_FAILURE,
  142. 								// so we need to refresh our connection.
  143. 				printfU(cU("Unknown function module: %s\n"), errorInfo.message);
  144. 			case RFC_EXTERNAL_FAILURE:	// Our function module implementation raised a SYSTEM_FAILURE. In this case
  145. 								// the connection needs to be refreshed as well.
  146. 				printfU(cU("SYSTEM_FAILURE has been sent to backend.\n\n"));
  147. 			case RFC_ABAP_MESSAGE:		// And in this case a fresh connection is needed as well
  148. 				serverHandle = RfcRegisterServer(serverCon, 3, );
  149. 				rc = errorInfo.code;
  150. 				break;
  151. 		}
  152. 		// This allows us to shutdown the RFC Server from the SAP system. The implementation of STFC_DEEP_TABLE
  153. 		// will set listening to false, if IMPORT_TAB-C == STOP.
  154. 		if (!listening){
  155. 			RfcCloseConnection(serverHandle, NULL);
  156. 			break;
  157. 		}
  158. 	}
  159. 	return 0;
  160. }
End of the code.