I have a program running on a server communicating with another program running on the client. They both sen开发者_开发知识库d data and files back and forth.
I notice that whenever there is a socHandler.read() (function to read data coming in on socket), it gets stuck waiting for data to arrive.
This is what the function looks like.
int CSocHandler::read(char * inBuffer, INT64 iBytesToRead){
bool blReadMore=false;
int retVal = 0;
int iOutputPointer = 0;
do{
blReadMore = false;
if (iStartOfBuffer == iEndOfBuffer) { //Buffer empty
if (blClosed ) {
return -1;
}
iStartOfBuffer = 0;
iEndOfBuffer = 0;
size_t bufferRemaining = BUFFER_SIZE-iEndOfBuffer;
int bytesRecvd = recv( sock, &buffer[iEndOfBuffer], (int)iBytesToRead<bufferRemaining?iBytesToRead:bufferRemaining), 0 );
if ( bytesRecvd <= 0) {
close();
Yield();
return retVal;
}
}
} while(blReadMore);
return retVal;
}
The variable sock is a type SOCKET and is a global variable defined elsewhere. How can I set the options or make this recv() call non-blocking only for this function call and no affect any other function?
I believe this is where it gets stuck waiting for data, and I want to make it timeout after X seconds.
Call select()
to query if the socket has any pending data before then calling recv()
to read it.
Use select(2)
on the socket before the recv
.
Using Perl syntax, it would look like
sub read_with_timeout {
my ($sock, $bytes_to_read, $timeout) = @_;
my $sel = IO::Select->new($sock);
my $end_time = Time::HiRes::time() + $timeout;
my $buf = '';
while ($bytes_to_read) {
$timeout >= 0 && () = $sel->can_read($timeout);
or die("Timeout");
my $rv = sysread($sock, $buf, $bytes_to_read, length($buf));
die "read: $!" if !defined($rv);
die "Premature eof" if !$rv;
$bytes_to_read -= $rv;
$timeout = $end_time - Time::HiRes::time();
}
return $buf;
}
can_read
is a call to select(2)
.
精彩评论