Setting a Timeout for Socket Operations

Set correctly timeout when connection fails on Python socket

Use socket.settimeout()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                           
s.settimeout(1.0)

This sets the timeout to 1 second.

socket.settimeout(value)

Set a timeout on blocking socket operations. The value argument can be a nonnegative float expressing seconds, or None. If a float is given, subsequent socket operations will raise a timeout exception if the timeout period value has elapsed before the operation has completed. Setting a timeout of None disables timeouts on socket operations. s.settimeout(0.0) is equivalent to s.setblocking(0); s.settimeout(None) is equivalent to s.setblocking(1).

How to set socket timeout in C when making multiple connections?

You can use the SO_RCVTIMEO and SO_SNDTIMEO socket options to set timeouts for any socket operations, like so:

    struct timeval timeout;      
timeout.tv_sec = 10;
timeout.tv_usec = 0;

if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
sizeof timeout) < 0)
error("setsockopt failed\n");

if (setsockopt (sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout,
sizeof timeout) < 0)
error("setsockopt failed\n");

Edit: from the setsockopt man page:

SO_SNDTIMEO is an option to set a timeout value for output operations. It accepts a struct timeval parameter with the number of seconds and microseconds used to limit waits for output operations to complete. If a send operation has blocked for this much time, it returns with a partial count or with the error EWOULDBLOCK if no data were sent. In the current implementation, this timer is restarted each time additional data are delivered to the protocol, implying that the limit applies to output portions ranging in size from the low-water mark to the high-water mark for output.

SO_RCVTIMEO is an option to set a timeout value for input operations. It accepts a struct timeval parameter with the number of seconds and microseconds used to limit waits for input operations to complete. In the current implementation, this timer is restarted each time additional data are received by the protocol, and thus the limit is in effect an inactivity timer. If a receive operation has been blocked for this much time without receiving additional data, it returns with a short count or with the error EWOULDBLOCK if no data were received. The struct timeval parameter must represent a positive time interval; otherwise, setsockopt() returns with the error EDOM.

C: socket connection timeout

This article might help:

Connect with timeout (or another use for select() )

Looks like you put the socket into non-blocking mode until you've connected, and then put it back into blocking mode once the connection's established.

void connect_w_to(void) { 
int res;
struct sockaddr_in addr;
long arg;
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;

// Create socket
soc = socket(AF_INET, SOCK_STREAM, 0);
if (soc < 0) {
fprintf(stderr, "Error creating socket (%d %s)\n", errno, strerror(errno));
exit(0);
}

addr.sin_family = AF_INET;
addr.sin_port = htons(2000);
addr.sin_addr.s_addr = inet_addr("192.168.0.1");

// Set non-blocking
if( (arg = fcntl(soc, F_GETFL, NULL)) < 0) {
fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
exit(0);
}
arg |= O_NONBLOCK;
if( fcntl(soc, F_SETFL, arg) < 0) {
fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
exit(0);
}
// Trying to connect with timeout
res = connect(soc, (struct sockaddr *)&addr, sizeof(addr));
if (res < 0) {
if (errno == EINPROGRESS) {
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
do {
tv.tv_sec = 15;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(soc, &myset);
res = select(soc+1, NULL, &myset, NULL, &tv);
if (res < 0 && errno != EINTR) {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
exit(0);
}
else if (res > 0) {
// Socket selected for write
lon = sizeof(int);
if (getsockopt(soc, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
exit(0);
}
// Check the value returned...
if (valopt) {
fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt)
);
exit(0);
}
break;
}
else {
fprintf(stderr, "Timeout in select() - Cancelling!\n");
exit(0);
}
} while (1);
}
else {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
exit(0);
}
}
// Set to blocking mode again...
if( (arg = fcntl(soc, F_GETFL, NULL)) < 0) {
fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
exit(0);
}
arg &= (~O_NONBLOCK);
if( fcntl(soc, F_SETFL, arg) < 0) {
fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
exit(0);
}
// I hope that is all
}

How to configure socket connect timeout

I solved the problem by using Socket.ConnectAsync Method instead of Socket.Connect Method.
After invoking the Socket.ConnectAsync(SocketAsyncEventArgs), start a timer (timer_connection), if time is up, check whether socket connection is connected (if(m_clientSocket.Connected)), if not, pop up timeout error.

private void connect(string ipAdd,string port)
{
try
{
SocketAsyncEventArgs e=new SocketAsyncEventArgs();

m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

IPAddress ip = IPAddress.Parse(serverIp);
int iPortNo = System.Convert.ToInt16(serverPort);
IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);

//m_clientSocket.
e.RemoteEndPoint = ipEnd;
e.UserToken = m_clientSocket;
e.Completed+=new EventHandler<SocketAsyncEventArgs>(e_Completed);
m_clientSocket.ConnectAsync(e);

if (timer_connection != null)
{
timer_connection.Dispose();
}
else
{
timer_connection = new Timer();
}
timer_connection.Interval = 2000;
timer_connection.Tick+=new EventHandler(timer_connection_Tick);
timer_connection.Start();
}
catch (SocketException se)
{
lb_connectStatus.Text = "Connection Failed";
MessageBox.Show(se.Message);
}
}
private void e_Completed(object sender,SocketAsyncEventArgs e)
{
lb_connectStatus.Text = "Connection Established";
WaitForServerData();
}
private void timer_connection_Tick(object sender, EventArgs e)
{
if (!m_clientSocket.Connected)
{
MessageBox.Show("Connection Timeout");
//m_clientSocket = null;

timer_connection.Stop();
}
}

Set timeout on Socket before it tries to connect

You may create an unconnected Socket with the default constructor and then call connect() with timeout.

Socket m_Socket = new Socket();
m_Socket.connect(addr,1000);

Does setting socket timeout cancel the initial request

It's unlikely that this can be made to work as you hope. An HTTP POST (as with any other HTTP request) is implemented by sending a command to the web server, then receiving a response. The python requests library encapsulates a lot of tedious parts of that for you, but at the core, it's going to do a socket send followed by a socket recv (it may of course require more than one send or recv depending on the size of the data).

Now, if you were able to connect to the web server initially (again, this is taken care of for you by the requests library but typically only takes a few milliseconds), then it's highly likely that the data in your POST request has long since been sent. (If the data you are sending is megabytes long, it's possible that it's only been partially sent, but if it is reasonably short, it's almost certainly been sent in full.)

That in turn means that in all likelihood the server has received your entire request and is working on it or has enqueued your request to work on it eventually. In either case, even if you break the connection to the server by timing out on the recv, it's unlikely that the server will actually even notice that until it gets to the point in its execution where it would be sending its response to your request. By that point, it has probably finished doing whatever it was going to do.

In other words, your socket timeout is not going to apply to the "HTTP request" -- it applies to the underlying socket operations instead -- and almost certainly to the recv part on the tail end. And just breaking the socket connection doesn't cancel the HTTP request.

There is no reliable way to do what you want without designing a transactional protocol with the close cooperation of the HTTP server.

You could do something (with the cooperation of the HTTP server still) that could do something approximating it:

  1. Create a unique ID (UUID or the like)
  2. Send a request to the server that contains that UUID along with the other account info (name, password, whatever else)
  3. The server then only creates the account if it hasn't already created an account with the same unique ID.

That way, you can request the operation multiple times, but know that it will only actually be implemented once. If asked to do the same operation a second time, the server would simply respond with "yep, already did that".

Will a python socket timeout?

socket.settimeout

From the docs:

socket.settimeout(value)
Set a timeout on blocking socket operations. The value argument can be a nonnegative float expressing seconds, or None. If a float is given, subsequent socket operations will raise a timeout exception if the timeout period value has elapsed before the operation has completed. Setting a timeout of None disables timeouts on socket operations. s.settimeout(0.0) is equivalent to s.setblocking(0); s.settimeout(None) is equivalent to s.setblocking(1).

So, if you don't call settimeout, your connection will remain open until you or the other host close it. And, of course, nothing goes wrong like a intermediary host goes down of any other failure.
Then, you have to monitor your connection and reopen if down.

How to set a timeout on blocking sockets in boost asio?

Under Linux/BSD the timeout on I/O operations on sockets is directly supported by the operating system. The option can be enabled via setsocktopt(). I don't know if boost::asio provides a method for setting it or exposes the socket scriptor to allow you to directly set it -- the latter case is not really portable.

For a sake of completeness here's the description from the man page:

SO_RCVTIMEO and SO_SNDTIMEO

          Specify the receiving or sending  timeouts  until  reporting  an
error. The argument is a struct timeval. If an input or output
function blocks for this period of time, and data has been sent
or received, the return value of that function will be the
amount of data transferred; if no data has been transferred and
the timeout has been reached then -1 is returned with errno set
to EAGAIN or EWOULDBLOCK just as if the socket was specified to
be non-blocking. If the timeout is set to zero (the default)
then the operation will never timeout. Timeouts only have
effect for system calls that perform socket I/O (e.g., read(2),
recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for
select(2), poll(2), epoll_wait(2), etc.


Related Topics



Leave a reply



Submit