Thread: UDP socket partial reading

  1. #1
    Alessio Stella
    Join Date
    May 2008
    Location
    Italy, Bologna
    Posts
    251

    UDP socket partial reading

    I have the following problem:
    I have to implement a communication with GigE cameras
    On the control protocol packet lenghts are under control so i can any time read just as many bytes as needed
    On the stream protocol instead evry time i am not sure how many bytes to read cause one packet might be missing and the following packet can be of different length

    So the question is:
    if a packet arrives of 9000 bytes and i perform a read of 756 bytes di i miss the rest of the packet??
    I supposed no but the answre seems yes as i made the following test:

    In the control protocol i substitued the following working code

    Code:
    	TimeOut.tv_sec=10;//CABLED
    	TimeOut.tv_usec=0;
    	if (SocketRead( Camera->CC.Socket, &(CCP_Ack) , sizeof(CCP_Ack), &TimeOut)) 
    	{
    		Log(&Lg,PrefixString,"SocketRead() error",0,LOG_ON_ERROR_ALSO);
    	 	sprintf(LogString,"Time out = %d %d ",TimeOut.tv_sec,TimeOut.tv_usec);
    	 	Log(&Lg,PrefixString,LogString,0,LOG_ON_ERROR_ALSO);
    	 	return(1);
    	 }
    with the following where the read was split in two
    Code:
    	TimeOut.tv_sec=10;//CABLED
    	TimeOut.tv_usec=0;
    	if (SocketRead( Camera->CC.Socket, &(CCP_Ack) , sizeof(CCP_Ack)-4, &TimeOut)) 
    	{
    		Log(&Lg,PrefixString,"SocketRead() error",0,LOG_ON_ERROR_ALSO);
    	 	sprintf(LogString,"Time out = %d %d ",TimeOut.tv_sec,TimeOut.tv_usec);
    	 	Log(&Lg,PrefixString,LogString,0,LOG_ON_ERROR_ALSO);
    	 	return(1);
    	 }
    	TimeOut.tv_sec=10;//CABLED
    	TimeOut.tv_usec=0;
    	if (SocketRead( Camera->CC.Socket, &(CCP_Ack.Reserved), 4, &TimeOut)) 
    	{
    		Log(&Lg,PrefixString,"SocketRead() error",0,LOG_ON_ERROR_ALSO);
    	 	sprintf(LogString,"Time out = %d %d ",TimeOut.tv_sec,TimeOut.tv_usec);
    	 	Log(&Lg,PrefixString,LogString,0,LOG_ON_ERROR_ALSO);
    	 	return(1);
    	 }
    The result was an error!!

    here is the code of SocketRead()
    Code:
    
    int SocketRead ( int sock, unsigned char* iBuffer , unsigned int iToReadByteNumber,  	struct timeval * TimeOut)
    {
    	//to be tested with signaling simulation and partial read (client sends only part of the message or too slowly)
     
     	int 		ToReadByteNumber;
     	int			ReadByteNumber;
     	unsigned char*		Buffer;
     	
     	fd_set mono_fd_set, read_fd_set;
     	int DataReady;
     	
     	struct timeval  TempTO;
     	
     	Type_LogString LogString;
     	
    
     	
    
     	
        FD_ZERO (&mono_fd_set);
        FD_SET (sock, &mono_fd_set);
     
     	ToReadByteNumber = iToReadByteNumber;
     	ReadByteNumber = 0;
     	Buffer           = iBuffer;
     
     	while ( ToReadByteNumber > 0 )
     	{
     		
            read_fd_set = mono_fd_set; 
         	TempTO=*TimeOut;
            //to be done upper limit on TimeOut in case of signal
    		DataReady=select (FD_SETSIZE, &read_fd_set, NULL, NULL, &TempTO);
            while (DataReady < 0)//Typically 1 sec //only to avoid peer-to-peer deadlock 
            { 
    
    		      	if (errno!=EINTR)
    		      	{
    		     	 		Log(&Lg,"SocketRead :: ","Read Error",0,LOG_ON_ERROR_ALSO);
    		           		return SOCKET_ERROR;
    		      	}
    		        read_fd_set = mono_fd_set; 
    		     	TempTO=*TimeOut;//TempT0;//it is not POSIX compliant to use TempTO cause it is not decremented in all implementations
            		DataReady=select (FD_SETSIZE, &read_fd_set, NULL, NULL, &TempTO);
            }  
            
     		//in case of EINTR chars should not be lost before the first read
            if (DataReady)
            {
            
            
    	    	ReadByteNumber = read( sock , Buffer , ToReadByteNumber );
    	    	//sprintf(LogString,"ReadByteNumber = %d ",ReadByteNumber); 
    	    	//Log(&Lg,"SocketRead :: ",LogString,0,LOG_ON_ERROR_NO);
    	    	if 	( ReadByteNumber < 0 )
    	       		{
    	       		if 	( errno != EINTR )//also SERVER_NON_CATASTROFIC_ERRNO must cause an error return code here
    	          		{
    	       			Log(&Lg,"SocketRead :: ","Read Error",0,LOG_ON_ERROR_ALSO);
    	          		return SOCKET_ERROR;
    	          		}
    	       		}
    	    	else if ( ReadByteNumber == 0 )
    	       		{
    	       		return SOCKET_CONNECTION_CLOSED;
    	       		}
    	    	else
    	    	{
    		    	ToReadByteNumber = ToReadByteNumber - ReadByteNumber;
    		    	Buffer = Buffer + ReadByteNumber;
    	    	}
        	
            }
            else
            {
            	Log(&Lg,"SocketRead :: ","TIME OUT",0,LOG_ON_ERROR_ALSO);
            	*TimeOut=TempTO;
          		return SOCKET_USER_DEFINED_TIMEOUT;
            }
            
        }
     
     	return SOCKET_OK;
     
    }
    same problems holds (+ a thread hanging) if i substitute the previous with this (without select)
    Code:
    int SocketRead ( int sock, unsigned char* iBuffer , unsigned int iToReadByteNumber,  	struct timeval * TimeOut)
    {
    	//to be tested with signaling simulation and partial read (client sends only part of the message or too slowly)
     
     	int 		ToReadByteNumber;
     	int			ReadByteNumber;
     	unsigned char*		Buffer;
     	
     	fd_set mono_fd_set, read_fd_set;
     	int DataReady;
     	
     	struct timeval  TempTO;
     	
     	Type_LogString LogString;
     	
    
     	
     	Log(&Lg,"SocketReadSimple :: ","Read",0,LOG_ON_ERROR_ALSO);
    
     
     	ToReadByteNumber = iToReadByteNumber;
     	ReadByteNumber = 0;
     	Buffer           = iBuffer;
     
     	while ( ToReadByteNumber > 0 )
     	{
     		
    
            
            
    	    	ReadByteNumber = read( sock , Buffer , ToReadByteNumber );
    	    	//sprintf(LogString,"ReadByteNumber = %d ",ReadByteNumber); 
    	    	//Log(&Lg,"SocketRead :: ",LogString,0,LOG_ON_ERROR_NO);
    	    	if 	( ReadByteNumber < 0 )
    	       		{
    	       		if 	( errno != EINTR )//also SERVER_NON_CATASTROFIC_ERRNO must cause an error return code here
    	          		{
    	       			Log(&Lg,"SocketRead :: ","Read Error",0,LOG_ON_ERROR_ALSO);
    	          		return SOCKET_ERROR;
    	          		}
    	       		}
    	    	else if ( ReadByteNumber == 0 )
    	       		{
    	       		return SOCKET_CONNECTION_CLOSED;
    	       		}
    	    	else
    	    	{
    		    	ToReadByteNumber = ToReadByteNumber - ReadByteNumber;
    		    	Buffer = Buffer + ReadByteNumber;
    	    	}
        	
     
            
        }
     
     	return SOCKET_OK;
     
    }
    May be the solution is suggested here http://www.opengroup.org/onlinepubs/.../xsh/read.html ?
    May be my read is in Message-discard mode ?
    Last edited by mynickmynick; 03-26-2009 at 03:27 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can I bind a UDP socket to a port, but send to any other port?
    By trillianjedi in forum Networking/Device Communication
    Replies: 3
    Last Post: 01-25-2009, 04:27 PM
  2. Error in creating socket in a client (UDP)
    By ferenczi in forum Networking/Device Communication
    Replies: 2
    Last Post: 11-27-2008, 11:11 AM
  3. Socket class OOD
    By lord mazdak in forum C++ Programming
    Replies: 6
    Last Post: 12-17-2005, 01:11 AM
  4. read/write through udp socket
    By xErath in forum Networking/Device Communication
    Replies: 3
    Last Post: 05-22-2005, 05:43 PM
  5. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM