[ Home | Syllabus | Course Notes | Assignments | Search]
Check out Assignment 3
Problem: where does the object exist:

void foo(int &x, int &y)
foo(a,a);
Dealing with the problems of passing parameters is called "parameter marshalling"
We will handle only the special cases of interest for version 2 at this time.
DCOM will need a more general RPC mechanism.
(complete source code here in two directories - client and server)
//************************** // packet.h : defines packet formats between client and server // for Version2 (CLIENT SIDE) // Also defines several utility functions (implemented in packet.cpp) // These send/receive control and packet information // and implement several WIN32 system calls as a client/server RPC // This RPC mechanism is limited to the needs of version2 // #ifndef PACKET_H #define PACKET_H #include <windows.h> #include <winsock.h>// also need "wsock32.lib" #include "Message.h" const int PORT = 44444; // pick some arbitrary port number typedef int NET_CONTROL; // REQUEST and REPLIES sent between client/server // REQUESTS/REPLIES: //Assign each win32 function a unique ID const NET_CONTROL CREATE_FILE = 123; const NET_CONTROL READ_FILE = 234; const NET_CONTROL WRITE_FILE = 345; const NET_CONTROL CLOSE_HANDLE = 456; const NET_CONTROL CREATE_DIRECTORY = 567; const NET_CONTROL SET_CURRENT_DIRECTORY = 678; const NET_CONTROL SET_FILE_POINTER = 789; const NET_CONTROL DELETE_FILE = 890; const NET_CONTROL SET_END_OF_FILE = 901;
const NET_CONTROL SUCCESS = 1; const NET_CONTROL FAILURE = -1; const int SIZE_NAME = 30; const int SIZE_BUFFER = 512; // . . . //**** RPC (Remote Procedure Call) section// same parameter list - append "client_" before function name HANDLE client_
CreateFile(LPCTSTR fileName, DWORD access, DWORD share, LPSECURITY_ATTRIBUTES dummy1, DWORD create, DWORD attributes, HANDLE templateFile); typedef struct { // input parameters
// only send the ones we need for simplicity char fileName[SIZE_NAME]; DWORD accessMode; DWORD createMode; } PCKT_CREATE_FILE_IN; typedef struct { // output parameters
NET_CONTROL status; // used to indicate any failures HANDLE fileHandle; } PCKT_CREATE_FILE_OUT; //***** WriteFile RPC section bool client_WriteFile(HANDLE fileHandle, LPCVOID buffer, DWORD nBytes, LPDWORD nBytesOut, LPOVERLAPPED dummy); typedef struct { // input parameters HANDLE fileHandle; BYTE buffer[SIZE_BUFFER]; DWORD nBytesIn; } PCKT_WRITE_FILE_IN; typedef struct { // output parameters NET_CONTROL status; DWORD nBytesOut; } PCKT_WRITE_FILE_OUT; // . . . // prototype for packet send/recieve functions
//** sendRequest - sends a request to the server bool sendControl(SOCKET, NET_CONTROL); NET_CONTROL getControl(SOCKET); bool sendPacket(SOCKET, LPBYTE packet, int size); bool getPacket(SOCKET, LPBYTE packet, int size);
//** sendControl - sends a network control word
// PRE: socket2client is ready for communications
// POST: sends "request" to socket2client
// on network failure - closes socket and cleans up TCP connection
bool sendControl(SOCKET socket2client, NET_CONTROL request)
{
char* Ptr = (char*) &request;
int numsnt = send(socket2client, Ptr, sizeof(request), 0);
if (numsnt != sizeof(request)) {
// . .
}
return true;
}
//******************************************
//** sendPacket: sends packet to socket2client
bool sendPacket(SOCKET socket2client, LPBYTE packet, int size)
{
int numsnt = send(socket2client, (char*) packet, size, 0);
if (numsnt != size) {
// . . .
}
return true;
}
bool getPacket(SOCKET socket2client, LPBYTE packet, int size)
{
int numrcv = recv(socket2client, (char*) packet, size,0);
if(numrcv != size)
return false;
return true;
}
//***********************************
//** client_WriteFile: simulates client side RPC for WriteFile
// does not support overlapped parameter
// PRE: socket2client connection is open
bool client_WriteFile(HANDLE fileHandle, LPCVOID buffer, DWORD nBytes, LPDWORD nBytesOut, LPOVERLAPPED dummy)
{
PCKT_WRITE_FILE_IN pcktWFin;
PCKT_WRITE_FILE_OUT pcktWFout;
// tell server to prepare to receive input parameters for WriteFile
if (!sendControl(socket2client, WRITE_FILE))
return false;
// Marshall input paramters
pcktWFin.fileHandle = fileHandle;
strncpy((char*)(pcktWFin.buffer), (char*)buffer, nBytes);
pcktWFin.nBytesIn = nBytes;
// sent input parameters to server
if(!sendPacket(socket2client, LPBYTE(&pcktWFin), sizeof(pcktWFin)))
return false;
// wait for completion and output parameters
if(!getPacket(socket2client, LPBYTE(&pcktWFout), sizeof(pcktWFout)))
return false;
if(pcktWFout.status != SUCCESS)
return false;
// Marshall output parameter
*nBytesOut = pcktWFout.nBytesOut;
return true;
}
// PACKET FORMATS: // Requests consist of two packets. // First packet is request type (which of the procedure calls to do) // Second Packet is the argument list for the procedure call // Response Packet is // Status (Success/Failure of RPC) // Return arguments // ....
while(TRUE) // loop until the connection goes down
{
request = getControl(socket2client);
switch (request)
{
case CREATE_FILE:
server_CreateFile(socket2client);
break;
// . . .
// Append "server_" before function name
// input parameter tells which SOCKET to get the "real" input parameters on
void server_CreateFile(SOCKET socket2client)
{
PCKT_CREATE_FILE_IN pcktCFin;
PCKT_CREATE_FILE_OUT pcktCFout;
HANDLE fileHandle;
if(!getPacket(socket2client, LPBYTE(&pcktCFin), sizeof(pcktCFin)))
{
// . .
}
fileHandle = CreateFile(pcktCFin.fileName, pcktCFin.accessMode,0,0, pcktCFin.createMode,0,0)
;
pcktCFout.status = SUCCESS;
pcktCFout.fileHandle = fileHandle;
if(!sendPacket(socket2client, LPBYTE(&pcktCFout), sizeof (pcktCFout))) {
// . . .
}
}
Replace File APIs with client version.
For Example:
bool CMessage::ReadMsg(HANDLE fileHandle)
{
DWORD nBytes;
if(!client_ReadFile(fileHandle,topic,SIZE_TOPIC+1,&nBytes,0))
return false;
if(!client_ReadFile(fileHandle,text,SIZE_TEXT+1,&nBytes,0))
return false;
return true;
}