int main(int argc, char ** argv) { CompleteSetupSystem css; PrintExampleDescription(); // Atypical usage: Capturing a file descriptor into a Socket object so that // it will be automatically close()'d when the execution leaves the enclosing scope { int some_fd = socket(AF_INET, SOCK_DGRAM, 0); Socket mySock(some_fd); // [...] // close(some_fd) will automatically be called here by the Socket object's destructor } // Still atypical, but this time we'll use a ConstSocketRef object so that we can // keep the file descriptor valid outside of the scope it was created in. { ConstSocketRef sockRef; { ConstSocketRef tempRef = GetConstSocketRefFromPool(socket(AF_INET, SOCK_DGRAM, 0)); sockRef = tempRef; // Share the reference outside our inner-local-scope // Note that the socket is NOT close()'d here, because sockRef still references it } // [...] // the socket IS closed here, because the last ConstSocketRef pointing to it (sockRef) is destroyed here } // Here's a more typical usage, via the NetworkUtilityFunctions.h API { ConstSocketRef sockRef = CreateUDPSocket(); // returns a ready-to-use UDP socket if (sockRef()) { printf("Allocated UDP socket ref: ConstSocketRef=%p, underlying fd is %i\n", sockRef(), sockRef.GetFileDescriptor()); // Code using the UDP socket could go here // [...] // UDP socket gets close()'d here } else printf("Failed to create the UDP socket!?\n"); } return 0; }
// This program is equivalent to the portableplaintext client, except // that we communicate with a child process instead of a socket. int main(int argc, char ** argv) { CompleteSetupSystem css; if (argc < 3) PrintUsageAndExit(); const uint32 numProcesses = atol(argv[1]); if (numProcesses == 0) PrintUsageAndExit(); const char * cmd = argv[2]; Hashtable<String,String> testEnvVars; (void) testEnvVars.Put("Peanut Butter", "Jelly"); (void) testEnvVars.Put("Jelly", "Peanut Butter"); (void) testEnvVars.Put("Oranges", "Grapes"); Queue<DataIORef> refs; for (uint32 i=0; i<numProcesses; i++) { ChildProcessDataIO * dio = new ChildProcessDataIO(false); refs.AddTail(DataIORef(dio)); printf("About To Launch child process #" UINT32_FORMAT_SPEC ": [%s]\n", i+1, cmd); fflush(stdout); ConstSocketRef s = (dio->LaunchChildProcess(argc-2, ((const char **) argv)+2, ChildProcessLaunchFlags(MUSCLE_DEFAULT_CHILD_PROCESS_LAUNCH_FLAGS), NULL, &testEnvVars) == B_NO_ERROR) ? dio->GetReadSelectSocket() : ConstSocketRef(); printf("Finished Launching child process #" UINT32_FORMAT_SPEC ": [%s]\n", i+1, cmd); fflush(stdout); if (s() == NULL) { LogTime(MUSCLE_LOG_CRITICALERROR, "Error launching child process #" UINT32_FORMAT_SPEC " [%s]!\n", i+1, cmd); return 10; } } StdinDataIO stdinIO(false); PlainTextMessageIOGateway stdinGateway; QueueGatewayMessageReceiver stdinInputQueue; stdinGateway.SetDataIO(DataIORef(&stdinIO, false)); SocketMultiplexer multiplexer; for (uint32 i=0; i<refs.GetNumItems(); i++) { printf("------------ CHILD PROCESS #" UINT32_FORMAT_SPEC " ------------------\n", i+1); PlainTextMessageIOGateway ioGateway; ioGateway.SetDataIO(refs[i]); ConstSocketRef readSock = refs[i]()->GetReadSelectSocket(); QueueGatewayMessageReceiver ioInputQueue; while(1) { int readFD = readSock.GetFileDescriptor(); multiplexer.RegisterSocketForReadReady(readFD); const int writeFD = ioGateway.HasBytesToOutput() ? refs[i]()->GetWriteSelectSocket().GetFileDescriptor() : -1; if (writeFD >= 0) multiplexer.RegisterSocketForWriteReady(writeFD); const int stdinFD = stdinIO.GetReadSelectSocket().GetFileDescriptor(); multiplexer.RegisterSocketForReadReady(stdinFD); if (multiplexer.WaitForEvents() < 0) printf("testchildprocess: WaitForEvents() failed!\n"); // First, deliver any lines of text from stdin to the child process if ((multiplexer.IsSocketReadyForRead(stdinFD))&&(stdinGateway.DoInput(ioGateway) < 0)) { printf("Error reading from stdin, aborting!\n"); break; } const bool reading = multiplexer.IsSocketReadyForRead(readFD); const bool writing = ((writeFD >= 0)&&(multiplexer.IsSocketReadyForWrite(writeFD))); const bool writeError = ((writing)&&(ioGateway.DoOutput() < 0)); const bool readError = ((reading)&&(ioGateway.DoInput(ioInputQueue) < 0)); if ((readError)||(writeError)) { printf("Connection closed, exiting.\n"); break; } MessageRef incoming; while(ioInputQueue.RemoveHead(incoming) == B_NO_ERROR) { printf("Heard message from server:-----------------------------------\n"); const char * inStr; for (int i=0; (incoming()->FindString(PR_NAME_TEXT_LINE, i, &inStr) == B_NO_ERROR); i++) printf("Line %i: [%s]\n", i, inStr); printf("-------------------------------------------------------------\n"); } if ((reading == false)&&(writing == false)) break; multiplexer.RegisterSocketForReadReady(readFD); if (ioGateway.HasBytesToOutput()) multiplexer.RegisterSocketForWriteReady(writeFD); } if (ioGateway.HasBytesToOutput()) { printf("Waiting for all pending messages to be sent...\n"); while((ioGateway.HasBytesToOutput())&&(ioGateway.DoOutput() >= 0)) {printf ("."); fflush(stdout);} } } printf("\n\nBye!\n"); return 0; }
void HandleSession(const ConstSocketRef & sock, bool myTurnToThrow, bool doFlush) { LogTime(MUSCLE_LOG_ERROR, "Beginning catch session (%s)\n", doFlush?"flush enabled":"flush disabled"); TCPSocketDataIO sockIO(sock, false); uint64 lastThrowTime = 0; uint8 ball = 'B'; // this is what we throw back and forth over the TCP socket! uint64 min=((uint64)-1), max=0; uint64 lastPrintTime = 0; uint64 count = 0; uint64 total = 0; SocketMultiplexer multiplexer; while(1) { int fd = sock.GetFileDescriptor(); multiplexer.RegisterSocketForReadReady(fd); if (myTurnToThrow) multiplexer.RegisterSocketForWriteReady(fd); if (multiplexer.WaitForEvents() < 0) { LogTime(MUSCLE_LOG_ERROR, "WaitForEvents() failed, aborting!\n"); break; } if ((myTurnToThrow)&&(multiplexer.IsSocketReadyForWrite(fd))) { int32 bytesWritten = sockIO.Write(&ball, sizeof(ball)); if (bytesWritten == sizeof(ball)) { if (doFlush) sockIO.FlushOutput(); // nagle's algorithm gets toggled here! lastThrowTime = GetRunTime64(); myTurnToThrow = false; // we thew the ball, now wait to catch it again! } else if (bytesWritten < 0) { LogTime(MUSCLE_LOG_ERROR, "Error sending ball, aborting!\n"); break; } } if (multiplexer.IsSocketReadyForRead(fd)) { int32 bytesRead = sockIO.Read(&ball, sizeof(ball)); if (bytesRead == sizeof(ball)) { if (myTurnToThrow == false) { if (lastThrowTime > 0) { uint64 elapsedTime = GetRunTime64() - lastThrowTime; count++; total += elapsedTime; min = muscleMin(min, elapsedTime); max = muscleMax(max, elapsedTime); if (OnceEvery(MICROS_PER_SECOND, lastPrintTime)) LogTime(MUSCLE_LOG_INFO, "count=" UINT64_FORMAT_SPEC" min=" UINT64_FORMAT_SPEC "us max=" UINT64_FORMAT_SPEC "us avg=" UINT64_FORMAT_SPEC "us\n", count, min, max, total/count); } myTurnToThrow = true; // we caught the ball, now throw it back! } } else if (bytesRead < 0) { LogTime(MUSCLE_LOG_ERROR, "Error reading ball, aborting!\n"); break; } } } }
virtual ConstSocketRef CreateDefaultSocket() { ConstSocketRef ret = DumbReflectSession::CreateDefaultSocket(); LogTime(MUSCLE_LOG_INFO, "MyDumbReflectSession(%p)::CreateDefaultSocket() called -- returning %p (socket_fd=%i)\n", this, ret(), ret.GetFileDescriptor()); return ret; }