title: Using router identity as an exit condition for a simple client/server program
body: <p>I have two separate C programs using CZMQ. One is a client and one is a server. The server transfers data from a file to the client, which writes the data received to a new file, called "testdata_out." Once the client receives the final chunk of data from the server, the client exits. </p>
  
  <p>The problem is that the server sits there, waiting to send more data to the client, but the client program has exited completely. I've had a look in GDB and the server just gets stuck at </p>
  
  <pre><code>zframe_t *identity = zframe_recv( router );
  </code></pre>
  
  <p>I've done detailed logging using fprintf() to confirm that this is the case.</p>
  
  <p>I'm using the <a href="http://zguide.zeromq.org/c:fileio3" rel="nofollow">ZMQ File transfer model 3</a> as my example - I've copied the exact code and test it to make sure it works as well.</p>
  
  <p>Basically I'm looking for ideas - what can I use as an exit condition if identity validation doesn't work? <strong>Could I send an abort signal somehow, since I can't edit the ZeroMQ function 'zframe_recv?' Or if someone can see what the problem is with my code or setup, a fix that lets me use ID validation as an exit condition would be awesome.</strong></p>
  
  <p>Here's the server function:</p>
  
  <pre><code>int zmq_send_internal_file( struct arg_struct *args )
  {
     struct arg_struct *input = (struct arg_struct *)args;
     int node_num = input-&gt;node;
     const char *fp = input-&gt;file_name;
     int chunkNum = 0;
     FILE *file_to_xfer = fopen( fp, "r" );
     zctx_t *ctx = zctx_new( );
     void *router = zsocket_new (ctx, ZMQ_ROUTER);
  
     //two parts per msg so HWM is size PIPELINE * 2
     zsocket_set_hwm (router, PIPELINE * 2);
     char *complete_address = "tcp://127.0.0.1:6000";
     if( 0 == zsocket_connect (router, complete_address ) )
     {
         printf("logging here\n");
     }
     else
     {
         printf("logging here\n");
     }
     while (true)
     {
          //what if we don't check the sender identity as a breaking condition?
          //what if we check chunk size as the breaking condition instead? - this causes program to exit too early
         //first frame in each message is the sender identity
         zframe_t *identity = zframe_recv( router );
         if (!identity)
         {
             printf("no identity, breaking.\n");
             break; //if we can't find an id, we're all set
         }
         //second frame is 'fetch' command
         char *command = zstr_recv (router);
         assert (streq (command, "fetch"));
         free (command);
  
         //third frame is chunk offset in file
         char *offset_str = zstr_recv (router);
         size_t offset = atoi (offset_str);
         free (offset_str);
  
         fprintf( fp_clnt_log, "%s : zmq:frame 4\n", time_str );
         //fourth frame is max chunk size
         char *chunksz_str = zstr_recv (router);
         size_t chunksz = atoi (chunksz_str);
         free (chunksz_str);
  
         //read chunk of data from file
         fseek (file_to_xfer, offset, SEEK_SET);
         byte *data = malloc (chunksz);
         assert (data);
  
         //send resulting chunk to client
         size_t size = fread (data, 1, chunksz, file_to_xfer);
         zframe_t *chunk = zframe_new (data, size);
         zframe_send (&amp;identity, router, ZFRAME_MORE);
         zframe_send (&amp;chunk, router, 0);
         chunkNum++;
     }
     if ( 0 == fclose( file_to_xfer ) )
     {
        printf("file_to_xfer closed successfully. \n");
     }
     else
     {
        printf("failed to close file_to_xfer. Exiting.\n");
        return -1;
     }
        return 0;
  }
  </code></pre>
  
  <p>Here's the client function:</p>
  
  <pre><code>void
  zmq_receive_file()
  {
     FILE *fp_out = fopen ("/usr/vos/bin/testdata_out","w");
     if ( NULL == fp_out )
     {
         printf( "fp_out pointer is NULL.\n");
     }
         return;
     }
  
     zctx_t *ctx = zctx_new ();
     void *dealer = zsocket_new (ctx, ZMQ_DEALER);
     zsocket_bind (dealer, "tcp://*:6000");
     //up to PIPELINE number of chunks can be in transit
     size_t credit = PIPELINE;
     size_t total = 0; //total bytes received
     size_t chunks = 0; //total chunks received
     size_t offset = 0; //offset of next chunk request
     int chunkNum = 0;
  
     while (true)
     {
         while (credit) //ask for next chunks until credit is 0
         {
             printf("%s : ft_server has credit, requesting next chunk...\n", time_str);
             zstr_sendm (dealer, "fetch");
             zstr_sendfm (dealer, "%ld", offset);
             chunkNum++;
             chunks++;
         }
  
         zframe_t *chunk = zframe_recv (dealer);
         if( !chunk )
         {
             break; //shut down and quit
         }
         //if there IS a chunk, write it to testdata_out
         else
         {
             size_t bytes_in_frame = zframe_size( chunk );
             char *data = zframe_data( chunk );
             fwrite( data, bytes_in_frame, 1, fp_out );
         }
  
         time_str = asctime( timeinfo );
         chunks++;
         credit++;
         size_t size = zframe_size (chunk);
         total+=size;
  
         if (size &lt; CHUNK_SIZE)
         {
             printf ( "%s : Chunk smaller than CHUNK_SIZE, all done.\n");
             break; //last chunk received, exit
  
  //program exits and leaves server hanging and waiting for an identity, so it never exits
         }
     }
     fclose( fp_out );
  }
  </code></pre>