From: Drizzt on
Hi all.

After a few tries, my co-workers are still fighting with the problems
with setsockopt, SO_RCVBUF and SO_SNDBUF, and the migration from a
server with Solaris 9 to a new server with Solaris 10.


Long story made short:
Process A open a listening socket and set both buffers to 700.000
setsockopt gives no err, and subsequent calls to getsockopt gives
700.000 for both buffers.

Then, process B opens a client connection to the above listening
socket. Again, bot buffer set to 700.000, both setsockopt calls return
no error, subsequent getsockopt report 700.000


The funny part:
Netstat gives, for the above situation, a connection from A to B with
both buffer set to ABOUT 700.000 and a connection from B to A with
buffer size of ABOUT 700.000 for A's RCVBUF and about 43.967 for the
SNDBUF of B.

The command they use is:
netstat -f inet | grep -i 9000

The result is:
localhost.50579 localhost.9000 43967 0 711660 0
ESTABLISHED
localhost.9000 localhost.50579 711648 0 703480 0
ESTABLISHED


And, even if we decide to not trust Netstat, what happens is that A
can write to B without problems, but after a few write to the socket
from B application, B hangs on the write function call.

What make everything really, really weird...are two even more funny
things:
- If we kill the B process, netstat immediately show SNDBUF of the
connection from B to A changing to 700.000
- The problem do not happens on the old server on a specific port
(8010), but fail on the others they tried. On the new server, it fails
even on the 8010 port.


It's a really strange behaviour, and not being a Unix C programmer
sound even more strange to me :-D



Following, is the code for the A process (the one the open the
listening end):
// Create socket
sock = socket (AF_INET, SOCK_STREAM, 0);

opt = 1;
ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,&opt,sizeof(opt));

memset(&address, 0x0, sizeof(address));

address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(9000);

ret = bind(sock, (const struct sockaddr*)&address, sizeof(address));


// Set receive buffer
bufsize = 700000;
ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize,
sizeof(bufsize));


// Set send buffer
bufsize = 700000;
ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize,
sizeof(bufsize));

// Enable keep alive
opt = 1;
ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));

// Delete enqued out of bound messages
ret = setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, 0, 0);


// Listen for connection
ret = listen(sock, 10);


--------------------------------------------------


And, this is the code for the client side:
/*
** Init socket
*/
if ((nFdSocket = socket (AF_INET, SOCK_STREAM, 0)) < 0)
return 0;

nOpt = 1;

/*
** Set i/o buffer's size
*/
nDimSockBuf = 700000;
err = setsockopt(nFdSocket, SOL_SOCKET, SO_RCVBUF, &nDimSockBuf,
sizeof(nDimSockBuf));
if(err < 0 )
{
printf("QSOCKET> Invalid RCVBUF\n");
return 0;
}

nDimSockBuf = 700000;
err = setsockopt(nFdSocket, SOL_SOCKET, SO_SNDBUF, &nDimSockBuf,
sizeof(nDimSockBuf));

if(err < 0 )
{
printf("QSOCKET> Invalid SNDBUF\n");
return 0;
}

err = setsockopt(nFdSocket, SOL_SOCKET, SO_REUSEADDR, &nOpt,
sizeof(nOpt));
if(err < 0 )
{
printf ("QSOCKET> Invalid REUSEADDR\n");
return 0;
}

nOpt = 1;
if (setsockopt(nFdSocket,IPPROTO_TCP,TCP_NODELAY,&nOpt,sizeof(nOpt))
<0)
return 0;

memset (&name, 0, sizeof (name));
name.sin_family = AF_INET;
name.sin_port = htons(9000);
memcpy(&name.sin_addr, host.h_addr_list[0], host.h_length);


if (connect(nFdSocket,(const struct sockaddr*)&name,sizeof(struct
sockaddr_in)) < 0)
{
close(nFdSocket);
nFdSocket = 0;
return 0;
}



--------------------------------------------------




Please...what the hell may it be???
Sun says that everything is ok. The sysadm says that both the servers
(the new one and the old one) are configured exactly the same. My co-
worker are going mad, and we risk to lose the customer. Currently they
have implemented a simple internal buffer, and it seems to work, but
we feel not much ok with a server that behave that way...



Thanks all, eventually :-)