Re: Scalable tcp server



Ignoring the issue of trying to send structs over a socket & the
Sleep() call, shouldn't your loop be something along the lines of the
following to handle a possible incomplete read of HEADER on your call
to Recv()?

// Peek for data
int nReadSoFar = 0 ;
while(1) {
if ((ret = m_Socket.Recv(
((char *) &H) + nReadSoFar
,sizeof(H)-nReadSoFar
,MSG_PEEK)) == SOCKET_ERROR)
return false;

// See if client is disconnected
if (ret == 0) return false;

nReadSoFar += ret ;
if(nReadSoFar >= (int) sizeof(NH)) {
break ;
}
Sleep(5);
}


On Jul 13, 8:55 am, h...@xxxxxxxxxxxxxxx wrote:
Thanks to everyone who has answered this so far.

As per suggestions I did some profiling and with a few small patches I
managed to boost the speed quite a bit. These patches were some
useless wait's here and there and some improvements with a little bit
of caching.

However now with those patches done I hit a new problem. Once in a
while I get errors on the client side and things just stop working.
This problem is *only* happening when I perform stress tests with
multiple socket connections.

I have identified it to be this piece of code on the client:

bool Csocket::SafeRecv()
{
int nIndex = 0;
int nLeft;
int ret;
HEADER H;

// Peek for data
do
{
if ((ret = m_Socket.Recv(&H, sizeof(H), MSG_PEEK)) ==
SOCKET_ERROR)
return false;

// See if client is disconnected
if (ret == 0) return false;

Sleep(5);
} while (ret < (int) sizeof(NH));

// The header has been received and tells you how much data is left
to receive.
nLeft = ENDIAN(H.lLength);

ResizeMemory(nLeft);

// Get the rest
while (nLeft > 0)
{
ret = m_Socket.Recv(&m_pBuffer[nIndex], nLeft, 0);
// Either the client disconnected or a socket error occured.
if (ret == SOCKET_ERROR) return false;
if (ret == 0) return false;

nLeft -= ret;
nIndex += ret;
}

return true;

}

I should make it clear that SOCKET_ERROR is defined as -1 and that
m_Socket.Recv() is just a wrapper around recv().

In the above code I read the header before reading rest of the data.
This is required in order to read how much more data is missing and
perform some cryptography services which I left out.

I have identified that something weird is going on with msg_peek since
"if (ret == 0) return false;" sometimes gets invoked. This means that
the server should have dropped the client connection but this is not
the case. I know that the server didn't do that just for the fun of
it.

Can anyone propose a better/ more safe way of achiving the same as
above?
What I want is to read the network header as 1 recv() before reading
rest of the data. This means that I'd like to wait on the client side
until I know that there is enough data to be read.

Thanks.

-- Henrik

.



Relevant Pages

  • Re: Linux 2.6.29.4
    ... static int is_efer_nx ... if (ret) ... struct ftdi_private { ... the specific security attributes of the socket ...
    (Linux-Kernel)
  • Re: [patch 01/03] USB: USB/IP: add common functions needed
    ... This adds the common functions needed by both the host and client side ... +int setnodelay(struct socket *socket) ... This header adds a lot of symbols which have fairly generic-sounding ...
    (Linux-Kernel)
  • [patch 01/03] USB: USB/IP: add common functions needed
    ... This adds the common functions needed by both the host and client side ... * GNU General Public License for more details. ... +static void usbip_dump_pipe(unsigned int p) ... +int setquickack(struct socket *socket) ...
    (Linux-Kernel)
  • TCP/IP - Sockets appear to be restricted to maximum 65,535 byte transfers
    ... A very simple pair of programs (Server and Client) are setup ... vanilla UCX v3.3 (without ECO), ... The Server process establishes a socket, listens for an accept on the ... main (int argc, char ** argv) ...
    (comp.os.vms)
  • Re: Wait on a server socket for 10 seconds
    ... I read the following code which open a server socket for client ... // Create socket for listening for client connection requests. ... int reliable_recvfrom(int fd, void *data, int size, int flags, ...
    (comp.unix.programmer)