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 ?