socket newbie, losing a few chars from server to client

This is a discussion on socket newbie, losing a few chars from server to client within the Linux Programming forums, part of the Platform Specific Boards category; Hi all, I'm new to sockets programming and this board, but I've learned a lot just by browsing. I wrote ...

  1. #1
    Registered User
    Join Date
    Jun 2003
    Posts
    41

    Unhappy socket newbie, losing a few chars from server to client

    Hi all,

    I'm new to sockets programming and this board, but I've learned a lot just by
    browsing.

    I wrote the below code. All I'm trying to do is read from PASSTHRU or INST,
    and pass one to the other. port[INST] is already up and running, as is
    port[PASSTHRU],hiowever port[PASSTHRU].clientSocket is only set when I get
    accept() from port[PASSTHRU].

    I can telnet to my server port fine, but if my server sends data from PASSTHRU
    to INST, and gets a response like

    Afg67 Cre.+ c

    then telnet only gets something like this

    fg67 Cr+c

    so some characters are missing. If I print the hex values RIGHT BEFORE I SENT
    it to the PASSTHRU.clientSocket socket, everything looks okay.

    I believe I set-up my serial device properly (INST) and my server ip port
    properly (PASSTHRU), however maybe not since I'm new to this.

    clientSocket is init to -1, which is why I check that value to see if this is
    the first time it's connected.

    Part of the problem is I know sleep(1) helps a lot, but I'm not allowed to do
    that. I need a proprietary close-sourced application to connect to my
    PASSTHRU socket and not even know I'm there! Thus, any artificial delays are
    bad. I can fiddle with artificial delays but there must be a better way...

    Anyway, here is the code I think it relevant. Any help is greatly appreciated,
    as I've been fiddling with this all day and I'm getting very discouraged. I'm
    using RH 7.x with the 2.4.18-14 kernel is it matters.

    Any help or hints or good jokes are GREATLY APPRECIATED!

    Josh


    Code:
    
    
    /* this will tell start_listening whether clientSocket
    exists on PASSTHRU socket */
    volatile sig_atomic_t passthruActive = 0;
    
    
    start_listening(...)
    
       unsigned int passthruClientLen;
       int maxfd = (port[REMORA].fd) + 1;
       int i, a, k, p;
       char input;
       int select_value;
       char head[4096];
       char tempbuf[4096];
       int num_bytes;
       fd_set    watchset;
       struct timeval loopdelay;
       FILE*  comm_file;
       
       ...
    
          /* all sockets are open, confirmed via netstat -l and can telnet no problem... */
    
          while (TRUE)
          {
             strcpy(tempbuf, "");
             strcpy(head, "");
             .
    	 .
    	 .
    	 loopdelay.tv_sec = 0; //SELECTDELAY;
             loopdelay.tv_usec = 0; /* must reset this for each call - select diddles it */
             FD_ZERO(&watchset);    /* clear all bits in this set */
             FD_SET(port[INST].fd, &watchset);     /* watch our data instrument */
             FD_SET(port[PASSTHRU].fd, &watchset); /* watch the passthru */
    
    	 if ((select_value = select(maxfd, &watchset, NULL, NULL, &loopdelay)) > 0)
             {
    	    if (FD_ISSET(port[PASSTHRU].fd, &watchset))
                {
                   /* we received something from our passthru */
    	       /* this should only happen upon the first connection */
    
                   /* first set our flag that passthru has priority until released */
                   passthruActive = 1;
    
                   if (port[PASSTHRU].clientSocket == -1)
                   {
                      /* this is our first client connection */
    
                      /* Set the size of the in-out parameter */
                      passthruClientLen = sizeof(port[PASSTHRU].clientAddress);
    
                      /* we've received data from the passthru port */
                      if ((port[PASSTHRU].clientSocket = accept(port[PASSTHRU].fd,
                                              (struct sockaddr *) &port[PASSTHRU].clientAddress,
                                              &passthruClientLen)) < 0)
                      {
                         ;//logger(logfile, "ERROR -- 9  We could not accept the call from the passthru socket");
                      } /* end if accept... */
                      else
                      {
    	             /* now that we've accepted the connection, listen */
    	             FD_SET(port[PASSTHRU].clientSocket, &watchset);
    
    	             /* must increase maxfd to listen to new client socket */
    	             if (port[PASSTHRU].clientSocket >= maxfd)
    	             {
                            maxfd = port[PASSTHRU].clientSocket + 1;
    	             } /* end if */
    
    	             /* now read from new client socket */
    	             num_bytes = read(port[PASSTHRU].clientSocket, head, port[PASSTHRU].size - (port[PASSTHRU].buf_idx + 1));
    
    	             if (num_bytes > 0)
    	             {
    	                strncpy(tempbuf, head, num_bytes);
    	                tempbuf[num_bytes] = 0x00; //add NULL
    			//tempbuf is only so I can printf for debugging, actuallly send head
    		        send_passthru_data_to_modem(head, port[INST].fd);
    	             } /* end if */
    
    	             else
    	             {
    	                /* we couldn't find any data on client socket?? */
    		        ;
    	             } /* end else */
    
                      } /* end else we could accept() */
    
                   } /* end if clientSocket == -1 */
    
                   else
                   {
    	          /* we've been here before, client is waiting... */
    	          /* now read from new client socket */
    	          num_bytes = read(port[PASSTHRU].clientSocket, head, port[PASSTHRU].size - (port[PASSTHRU].buf_idx + 1));
    
    	          if (num_bytes > 0)
    	          {
    	             strncpy(tempbuf, head, num_bytes);
    	             tempbuf[num_bytes] = 0x00; //add NULL
                         //tempbuf is only for debugging via printf....actually send head
                         /* our client socket was previously established */
                         send_passthru_data_to_modem(head, port[INST].fd);
    
                      } /* end if */
    
                   } /* end else */
    
                } /* end if PASSTHRU */
    
    
                if (FD_ISSET(port[INST].fd, &watchset))
                {
                   /* we're told something is waiting from the data device */
                   num_bytes = read(port[INST].fd, head, port[INST].size - (port[INST].buf_idx - 1));
    
    	       /* see if we have any data to read */
                   if (num_bytes > 0)
                   {
                      strncpy(tempbuf, head, num_bytes);
    	          tempbuf[num_bytes] = 0x00; //add NULL
    
    	          /* test to see if must transfer the data untouched, or we can modify it */
    	          if (passthruActive == 1)
                      {
                         /* passthru is active, so just send whatever modem sent us */
                         /* back out thru passthru */
                         for (a = 0; a < strlen(tempbuf); a++)
    		     {
    			printf("[%i]:%i ", a, tempbuf[a]);
    		     }
    		     printf("  TO PASTHRU:\n%s\n", tempbuf);
    		     //tempbuf looks good dangit!! send head, which should be just like tempbuf wo/NULL
                         send_modem_data_to_passthru(head, port[PASSTHRU].clientSocket);
                      } /* end if passthruActive */
    
    	          else if (passthruActive == 0)
    	          {
    	             /* write the data we received to our traffic file */
    		     ;
    
    	          } /* end else if passthruActive == 0 */
    
    	          else
    	          {
                         /* passthruActive is neither 0 nor 1, which should never happen!! */
                         ;
                      } /* end else */
    
                   } /* end if num_bytes > 0 */
    
                } /* end if FD_ISSET [INST] */
    
             } /* end if select */
    
          } /* end while loop */
    
       } /* end init_data_device() loop */
    
       else
       {
          logger(logfile, "ERROR -- 8 We could not initialize our data device");
          return (FALSE);
       } /* end else if data device returned FALSE */
    
       return (TRUE);
    
    } /* end listening(...) */
    
    
    
    
    
    int send_passthru_data_to_modem(char *input_buffer, int modem_fd)
    {
       tcdrain(modem_fd);
       /* take everything we got from the passthru socket and give it to modem */
       return (write(modem_fd, input_buffer, sizeof(input_buffer)));
    
    } /* end send_passthru_data_to_modem(...) */
    
    int send_modem_data_to_passthru(char *input_buffer, int passthruSocket)
    {
       tcdrain(psthruSocket);
       return (write(passthruSocket, input_buffer, sizeof(input_buffer)));
    } /* end send_modem_data_to_passthru(...) */

  2. #2
    Registered User
    Join Date
    Jun 2003
    Posts
    41
    I don't know if it helps, but it seems like if I send a <CR> thru
    telnet, the serial device behaves as if I sent two <CR>. This makes
    me think the serial port is echoing stuff, but as far as I know I
    turned all of that off. How I configured the serial port (INST) is
    below. The ip socket (PASSTHRU) is very standard (socket using
    AP_INET, SOCK_STREAM, IPPROTO_TCP...). Since some chars seem missing
    on returning to the clientSocket (telnet as a test), I tried to turn
    off every blocking or delay feature.....


    Code:
    / **************************************************
     Procedure: open_client_serial_port(...)
    
     Purpose: Attempts to open the serial port passed-in as parameter 'port'
    
     Returns: int: 1 if the serial device could not be opened
    
     Notes: This might also 'exit' and not just 'return' if we could not open our
     serial device!
     **************************************************/
    int open_client_serial_port(comm_data_t* port,
                                const comm_connection_t* environment,
    			    FILE* logfile)
    {
       int		retval = 0;    /* our return value */
    
       port->fd = open(port->dev, O_RDWR | O_NOCTTY | O_NDELAY);
       if (port->fd < 0)
       {
          logger(logfile, "ERROR -- 2 Could not open our serial device");
          perror(port->dev);
          retval = 1;
          port->comm_status = COMM_DOWN;
       }
       else
       {
          /* we could open our serial port */
    
          logger(logfile," -- Debug: 2 Successfully opened our serial device");
    
          tcgetattr(port->fd,&port->ser_oldtio); // save the current modem setting so we can restore them
          tcgetattr(port->fd,&port->ser_newtio); // save the current modem settings to the new settings structure
          cfmakeraw(&port->ser_newtio); // set struct for new term settings to raw.  See man 'cfmakeraw'
          port->ser_newtio.c_cflag &= ~CRTSCTS; // make sure rts/cts flow control is turned off
          port->ser_newtio.c_cflag |= (CLOCAL | CREAD); // make sure receiver is enabled and port owner not changed
          port->ser_newtio.c_iflag &= ~(ISIG | IXON | IXOFF | IXANY);// make sure software flow control is off
          cfsetispeed(&port->ser_newtio, B9600);	// set the input baudrate for new terminal settings
          cfsetospeed(&port->ser_newtio, B9600); // set the output baudrate for new terminal settings
          tcgetattr(1,&port->ser_old_stdout_tio);	// we gotta do this - there is a Linux bug
          tcsetattr(1,TCSANOW,&port->ser_newtio); // make stdout settings like modem settings
          tcgetattr(0,&port->ser_oldstdtio); // get stdin settings for restoration ...
          tcgetattr(0,&port->ser_newstdtio); // ... and use them as a basis for changes
          port->ser_newstdtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make them raw
          tcflush(port->fd, TCIOFLUSH); // clear the input and output port buffers
          tcsetattr(0,TCSANOW,&port->ser_newstdtio); // set the new attributes immediately
          tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new attributes for the serial port immediately
    
          port->comm_status = COMM_OK; //we really need some error checing on all of the above calls ...
       }
    
       if (port->fd < 0)
       {
          logger(logfile, "ERROR -- 2b Could not open our serial device");
          perror(port->dev);
          exit(-1);
       }
    
       //set the serial port to return immediately after a read
       fcntl(port->fd, F_SETFL, O_NONBLOCK);
    
       return(retval);
    
    } /* end open_client_serial_port */

  3. #3
    Registered User
    Join Date
    Jun 2003
    Posts
    41
    Oops, what a dumb mistake! Thanks for the second pair of eyes, I really appreciate it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. server client application - (i really need your help)
    By sarahnetworking in forum C Programming
    Replies: 3
    Last Post: 03-01-2008, 10:54 PM
  2. Socket Programming Problem!!!!
    By bobthebullet990 in forum Networking/Device Communication
    Replies: 2
    Last Post: 02-21-2008, 07:36 PM
  3. Where's the EPIPE signal?
    By marc.andrysco in forum Networking/Device Communication
    Replies: 0
    Last Post: 12-23-2006, 08:04 PM
  4. Unicode vurses Non Unicode client server application with winsock2 query?
    By dp_76 in forum Networking/Device Communication
    Replies: 0
    Last Post: 05-16-2005, 08:26 AM
  5. Server Client Messaging Program
    By X PaYnE X in forum Networking/Device Communication
    Replies: 3
    Last Post: 01-04-2004, 05:20 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21