View mode: basic / threaded / horizontal-split · Log in · Help
September 26, 2011
Socket.send
I'm working on a simple server written in d. I use a SocketSet to
check requests from clients.

I have to send back response and close connection. Is there a method
to check if socket sent data or not with an async socket (so i can
close it)?
September 26, 2011
Re: Socket.send
Am 26.09.2011 18:09, schrieb Andrea Fontana:
> I'm working on a simple server written in d. I use a SocketSet to
> check requests from clients.
> 
> I have to send back response and close connection. Is there a method
> to check if socket sent data or not with an async socket (so i can
> close it)?

Simply use SocketSet and do some kind of select. You'll read 0 bytes
from it, if it has disconnected.
September 27, 2011
Re: Socket.send
I'll try to explain it better.

if i write:

socket.send(...);
socket.close();
socket = null;

and send is async, i guess sending will not work properly in this way.

How do i know if send() is still sending or not?
September 27, 2011
Re: Socket.send
On Tue, 27 Sep 2011 01:40:49 +0100, Andrea Fontana <advmail@katamail.com>  
wrote:

> I'll try to explain it better.
>
> if i write:
>
> socket.send(...);
> socket.close();
> socket = null;
>
> and send is async, i guess sending will not work properly in this way.
>
> How do i know if send() is still sending or not?

I am not sure of the D socket API, but here is how you do it with the  
underlying BSD sockets API..

The recommended 'graceful' way to close sockets is to use shutdown(SEND)  
and then wait on recv/select until the remote end has read all the data  
and signalled shutdown back, for example..

[endpoint-1] .. wants to send and close:

  send(s..);                // send last response
  .. read any expected replies..
  shutdown(s, SD_SEND);     // tell the other end you will send no more  
data
  .. call recv, if != 0; check for WSAEWOULDBLOCK/EWOULDBLOCK, call  
select, loop until recv returns 0 ..
  close(s);                 // close


[endpoint-2] .. will react to this in the following way:

  some_loop()
  {
    bytes = recv(s..);      // reading data..
    if(bytes == 0) break;   // no more data
    else if(bytes == SOCKET_ERROR) .. call select, loop ..
    ..etc..
  }
  shutdown(s, SD_SEND);     // tell the other end you will send no more  
data
  .. call recv, if != 0; check for WSAEWOULDBLOCK/EWOULDBLOCK, call  
select, loop until recv returns 0 ..
  close(s);                 // close

So.. recv returns 0 if the other calls shutdown(SD_SEND) or close(), so  
even if endpoint-2 is badly behaved and just calls close you will notice -  
you just might get a "connection reset" error.  With non blocking sockets  
recv returns immediately with SOCKET_ERROR (-1) if there is no data, and  
the "last error" will be EWOULDBLOCK, in which case you can sleep or  
select and retry the recv until you get a return of 0, meaning socket  
closed.

If you don't do this, and call close too soon the remote end will get a  
'connection reset by peer' error, due to the locally buffered (unsent)  
data.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
September 27, 2011
Re: Socket.send
On Tue, 27 Sep 2011 10:53:13 +0100, Regan Heath <regan@netmail.co.nz>  
wrote:
>    .. call recv, if != 0; check for WSAEWOULDBLOCK/EWOULDBLOCK, call   
> select, loop until recv returns 0 ..

In this loop you will also need to check for WSAECONNRESET/ECONNRESET to  
detect a badly behaved remote end calling close without shutdown/recv  
itself.  You can either chose to swallow/ignore this error, or to  
log/trace it, whatever is suitable to your application.  I would not  
recommend throwing an exception or treating it like a failure .. unless  
you control the code on both ends of the connection as it might indicate a  
bug in your code.

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
September 27, 2011
Re: Socket.send
It's a small server (http) so I don't wait for any reply from the
client. If there's an header "connection: close", server should
close connection when data is sent.

So on server side i should write:

if (httpRequest.isCompleted)
{
  // Parsing request headers
  [... omitted ...]
  // Build http reply
  [... omitted ...]

  socket.send(reply);
  socket.shutdown(SocketShutdown.BOTH);
}


and then wait for client to close connection?
September 27, 2011
Re: Socket.send
On Tue, 27 Sep 2011 11:20:32 +0100, Andrea Fontana <advmail@katamail.com>  
wrote:

> It's a small server (http) so I don't wait for any reply from the
> client. If there's an header "connection: close", server should
> close connection when data is sent.
>
> So on server side i should write:
>
> if (httpRequest.isCompleted)
> {
>    // Parsing request headers
>    [... omitted ...]
>    // Build http reply
>    [... omitted ...]
>
>    socket.send(reply);
>    socket.shutdown(SocketShutdown.BOTH);
> }
>
>
> and then wait for client to close connection?

Almost.  If the client sends additional data which you do not read above,  
then shutdown(BOTH) may cause a "connection aborted" error on the client  
end.  Ideally you want to shutdown(SEND) only, then loop reading all  
remaining data from the socket (until receive returns 0), then call  
close().

I've just looked at std.socket and I can't see a nice easy way to call  
select on just the one/current socket.. I was expecting  
socket.select(READ|WRITE|EXCEPT) helper functions or similar :(

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
Top | Discussion index | About this forum | D home