home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // This program illustrates a simple server implementation
- // The server is listening on the tcp and udp ports
- //-----------------------------------------------------------------------------
-
- #ifdef WIN32
- #include <windows.h>
- #endif
- #include <stdio.h>
- #include <math.h>
-
- #include <rpcdc.h>
-
- //-----------------------------------------------------------------------------
- // Here is a definition of a structure that must be transmitted to the server
- // One possibility is to develop a specific XDR function, used with transmit/
- // receive functions
- //-----------------------------------------------------------------------------
- typedef struct _TEST {
-
- int i1;
- int i2;
- int i3;
-
- float f;
- double d;
-
- } TEST;
-
- //-----------------------------------------------------------------------------
- // First write the XDR function - standard structure
- // The parameters are as follows :
- // h : (void *) points to the host binary representation of the data
- // n : (void *) points to the network binary representation of the data
- // code : indicates the operation to perform (3 possibilities)
- // --> XDR_ENCODE : conversion h -> n
- // --> XDR_DECODE : conversion n -> h
- // --> XDR_MEMORY : just returns the size of the object
- //-----------------------------------------------------------------------------
- size_t _xdr_TEST (void *h, void *n, int code)
-
- {
- TEST *hi=(TEST *)h; // first convert pointers
- char *ni=(char *)n;
- size_t size;
-
- switch (code) {
-
- case XDR_ENCODE:
- case XDR_DECODE:
-
- size=_xdr_int(NULL,NULL,XDR_MEMORY);
- _xdr_int((void *)&hi->i1,(void *)ni,code); ni+=size;
- _xdr_int((void *)&hi->i2,(void *)ni,code); ni+=size;
- _xdr_int((void *)&hi->i3,(void *)ni,code); ni+=size;
-
- size=_xdr_float(NULL,NULL,XDR_MEMORY);
- _xdr_float((void *)&hi->f,(void *)ni,code); ni+=size;
-
- size=_xdr_double(NULL,NULL,XDR_MEMORY);
- _xdr_double((void *)&hi->d,(void *)ni,code); ni+=size;
- return 0;
-
- case XDR_MEMORY:
- default:
- return 3*_xdr_int(NULL,NULL,XDR_MEMORY)+
- _xdr_float(NULL,NULL,XDR_MEMORY)+
- _xdr_double(NULL,NULL,XDR_MEMORY);
- }
- }
-
- //-----------------------------------------------------------------------------
- // Now the function to send a TEST structure becomes very simple !
- // The following example returns 1 if success, 0 if a problem occurs.
- // Binary conversion is automatically performed through the XDR routine
- // written above.
- // Warning : remember to call _rpc_flush() !
- //-----------------------------------------------------------------------------
- int _rpcsend_TEST (SOCKET Socket,
- RPC_MSG *rpc_msg, XDR_BUFFER *xdr_buffer,
- TEST *TestParameter)
-
- {
- return _rpcsend_buffer(Socket,rpc_msg,xdr_buffer,TestParameter,_xdr_TEST)==
- _xdr_TEST(NULL,NULL,XDR_MEMORY);
- }
-
- //-----------------------------------------------------------------------------
- // Similarly, the function to receive a TEST structure is also simple.
- // Binary conversion is automatically performed through the XDR routine
- // written above.
- //-----------------------------------------------------------------------------
- int _rpcrecv_TEST (SOCKET Socket,
- XDR_BUFFER *xdr_buffer,
- TEST *TestParameter)
-
- {
- return _rpcrecv_buffer(Socket,xdr_buffer,TestParameter,_xdr_TEST)==
- _xdr_TEST(NULL,NULL,XDR_MEMORY);
- }
-
- //-----------------------------------------------------------------------------
- // This is one of the most important functions : each time a message is
- // received by the server, this function is called
- // The first parameter rpc_func identifies the message
- // The second parameter idClient identifies the client (the server can accept
- // connections with multiple clients at the same time)
- //-----------------------------------------------------------------------------
- static void Dispatch (int rpc_func, int idClient)
-
- {
- SOCKET socket;
- RPC_MSG *rpc_msg;
- XDR_BUFFER *xdr_buffer;
- char *client_buffer;
- int I;
- TEST Test;
-
- // The first thing to do is to retrieve the parameters of the client
- _GetClientInfo(idClient,
- &socket,
- &rpc_msg,
- &xdr_buffer,
- &client_buffer);
-
- // Now, the function reduces to a big switch depending of the value of rpc_func
- switch (rpc_func) {
-
- // First kind of message (prefer constants defined by #define instead of numerical constants)
- // This message requires to read additionnal parameters (int + TEST strcuture) from the socket
- // The response of the server to the client : just add 1 to the int sent by the client, and then return it
- // Similar changes to the TEST structure
- // Note the call to _rpc_flush() !
- case 1:
- _rpcrecv_int(socket,xdr_buffer,&I);
- _rpcrecv_TEST(socket,xdr_buffer,&Test);
- printf("Data received from client : %d\n",I);
- printf("TEST structure : %d %d %d %g %lg\n",Test.i1,Test.i2,Test.i3,Test.f,Test.d);
- // Now change the values
- I++;
- Test.i1*=2;
- Test.i2*=3;
- Test.i3*=4;
- Test.f=1.0f/Test.f;
- Test.d=sqrt(Test.d);
- // Now returns to changes parameters to client
- _rpcsend_int(socket,rpc_msg,xdr_buffer,I);
- _rpcsend_TEST(socket,rpc_msg,xdr_buffer,&Test);
- _rpc_flush(socket,rpc_msg);
- break;
-
- // Other messages and associated code ...
-
- default:
- return;
- }
- }
-
- //-----------------------------------------------------------------------------
- // This accepts or not a connection from one client on the network, whose ip
- // address is transmitted as a character string parameter. The return value is
- // 0 (connection refused) or 1 (connection accepted)
- //-----------------------------------------------------------------------------
- static int AcceptConnection (char *ip)
-
- {
- return 1;
- }
-
- //-----------------------------------------------------------------------------
- // This function is called each time a message is received on the udp socket
- // of the server (if it exists).
- // In this example, the server sends an answer made of one long int, followed
- // by a 128 characters string.
- //-----------------------------------------------------------------------------
- void udpManager (SOCKET udpSocket)
-
- {
- sockaddr_in src_addr;
- long int udpQuery;
- int stat,len;
- struct {
- long int udpResponse;
- char szb[128];
- } udp;
-
- // First I read the data from the udp socket. In this example, the client is assumed to send
- // only a 32 bits message
- len=sizeof(src_addr);
- stat=recvfrom(udpSocket,(char *)&udpQuery,sizeof(long int),0,(struct sockaddr *)&src_addr,&len);
- if (stat!=sizeof(long int)) return;
- // Note the use of ntohl(), required by the XDR mechanism
- udpQuery=ntohl(udpQuery);
-
- // Depending on the received message, I generate the answer, replying (udpQuery+1)
- switch (udpQuery) {
- case 1:
- udp.udpResponse=htonl(1+udpQuery); // response=query+1
- strcpy(udp.szb,"udp query #1"); // text of the response
- break;
- default:
- udp.udpResponse=htonl(0); // response=0
- strcpy(udp.szb,""); // empty text
- }
-
- // Now send the response to the client who sent the udp request
- sendto(udpSocket,(char *)&udp,sizeof(udp),MSG_DONTROUTE,(struct sockaddr *)&src_addr,sizeof(sockaddr_in));
- }
-
- //-----------------------------------------------------------------------------
- // This function starts the server with a specific service
- //-----------------------------------------------------------------------------
- static void Start (char *service)
-
- {
- int stat;
- SOCKET tcpSocket,udpSocket;
- char msg[256];
-
- stat=_StartServerDaemon(service,
- 10, // timeout en rΘception : 60 secondes par dΘfaut
- "", // no log file
- 0, // no client data
- NULL, // Constructor=NULL (no client data)
- NULL, // Destructor=NULL (no client data)
- Dispatch, // Dispatch function written above
- AcceptConnection, // Acceptation function written above
- udpManager, // udpManager function written above
- NULL, // registration information
- &tcpSocket, // tcp socket created by this function if successful
- &udpSocket); // udp socket created by this function if successful
-
- // An error has occured ! print the error message and leave.
- if (!stat) {
- _GetErrMsg(msg);
- printf("%s\n",msg);
- return;
- }
-
- // Now start the infinite loop of the server
- _ServerMainLoop(NULL);
-
- // The program should never reach this point !
- _StopServerDaemon(tcpSocket,udpSocket);
- }
-
- //-----------------------------------------------------------------------------
- int main (int argc, char **argv)
-
- {
- if (argc!=2) {
- printf("usage : %s <service>\n",argv[0]);
- return 0;
- }
-
- Start(argv[1]);
-
- return 0;
- }
-