By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,812 Members | 863 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,812 IT Pros & Developers. It's quick & easy.

C#'s Socket.Connect returns normally but socket isn't connected.

P: n/a
I'm creating a socket as follows:

m_networkSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
m_networkSocket.LingerState = new LingerOption(true, 1);
m_networkSocket.Blocking = true;
m_networkSocket.SetSocketOption(SocketOptionLevel. Socket,
SocketOptionName.NoDelay, true);
m_networkSocket.SetSocketOption(SocketOptionLevel. Socket,
SocketOptionName.KeepAlive, !persistentConnection);

IPEndPoint them = new IPEndPoint(IPAddress.Parse(hostname), port);
try
{
m_networkSocket.Connect(them);
Debug.Assert(m_networkSocket.Connected,
"Connect() returned but we're not connected! Socket is: " +
m_networkSocket);
}
catch (SocketException se)
{
System.Console.WriteLine("connect caught: " + se);
}

After writing (synchronously) I close it thus:

m_networkSocket.Shutdown(SocketShutdown.Send);
m_networkSocket.Disconnect(false);
m_networkSocket.Close();
m_networkSocket = null;

The design requires that I open, write & close the socket for each message
I'm sending (the network might be unreliable, so a persistent connection
won't work). The whole thing runs in a single thread, taking messages out
of a queue (other threads insert messages into the queue).

The problem I've run into is that this works fine for the first block of
messages (I've tried batches of 16, 32 and 64 messages, with messages sent
in rapid succession). This first batch always works. I let a few seconds
pass, then send another batch. Sometimes the 2nd batch works, sometimes
not. If it fails it trips on the Debug.Assert immediately after the call
to Connect().

If it's returning from Connect() without throwing anything I'd _assumed_
that the connect worked - but the failure to pass the assertion tells me
other wise!

Anybody have any ideas as to what might be going on? I'm somewhat new to
socket programming, very new to Microsoft. We're using Visual Studio 2005
on XP Pro SP2.

thanks

--
Al Dunstan, Software Engineer
OptiMetrics, Inc.
3115 Professional Drive
Ann Arbor, MI 48104-5131
Sep 9 '08 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On Tue, 09 Sep 2008 11:59:51 -0700, A. W. Dunstan <no@spam.thankswrote:
[...]
The problem I've run into is that this works fine for the first block of
messages (I've tried batches of 16, 32 and 64 messages, with messages
sent
in rapid succession). This first batch always works. I let a few
seconds
pass, then send another batch. Sometimes the 2nd batch works, sometimes
not. If it fails it trips on the Debug.Assert immediately after the call
to Connect().

If it's returning from Connect() without throwing anything I'd _assumed_
that the connect worked - but the failure to pass the assertion tells me
other wise!

Anybody have any ideas as to what might be going on? I'm somewhat new to
socket programming, very new to Microsoft. We're using Visual Studio
2005
on XP Pro SP2.
Fundamentally, the issue is that you're relying on a property that isn't
reliable. It won't return the instantaneous state of the socket, but
rather the state known at some previous time. Even if it did return the
instantaneous state, that state could change between the time you check it
and the time you try to rely on it.

When Connect() returns, the socket _has_ successfully connected to the
remote endpoint. However, you can't make any assumptions beyond that.
The internal data associated with the Connected property might not be
updated yet or the connection could wind up getting reset immediately
after connection. You simply need to write your code so that it can deal
with errors during later operations.

Speaking of which, given that, it really doesn't make sense to keep
recreating connections just because of a reliability issue. If anything,
the extra overhead _increases_ your exposure to reliability issues. Every
time any data is moved from one endpoint to the other, you run the risk of
a reliability problem causing an error. The only thing that recreating
connections does is cause _more_ data to be moved, increasing the risk of
an error.

Likewise, using the KeepAlive option will also have only that effect.
Given that the connections appear to be transient anyway, it's not clear
why you're using that. But given that you are, all it does is increase
your chances of having an error occur when one otherwise would not have.
Keep-alives can be useful in some very specific scenarios, but it's not an
appropriate approach to error management. That's not what it's there for.

Setting the Blocking property to "true" is superfluous. That's the
default.

Setting the NoDelay option is generally a bad idea, and it is especially
so in your particular scenario. It's bad generally because it decreases
efficiency of the connection. It's especially bad in your case for the
same reason that recreating the connection is: it has the effect of
_adding_ to the amount of data that needs to be moved, which increases
your odds of getting an error on the unreliable connection.

Finally, if you care about reliability, you should not rely on the
LingerState of the socket. Leave the socket as the default, and then
after you've called Shutdown(), call Receive() until it returns 0
(assuming the remote endpoint isn't actually going to send you anything,
that will happen as soon as the remote endpoint has received all of your
data). Unless you do that, you have no assurance that the remote endpoint
has actually received all of the data you sent, even using a lingering
socket.

In other words, I would take out almost all of the implementation details
you've posted, including the part of the design in which a new connection
is repeatedly reestablished. Just design the code so that it can recover
gracefully from a reset connection and otherwise leave the socket
connected. Don't bother with lingering, keep-alives, or disabling Nagle
(i.e. "NoDelay"), and do make sure you do a true graceful shutdown by
calling Receive() after Shutdown().

Right now, the code is written in a way that is likely to maximize the
number of errors. You're working against TCP, rather than with it.
That's never a good approach anyway, but especially when you _know_ you
have an unreliable connection, it's just going to hurt.

Pete
Sep 9 '08 #2

P: n/a
im new to .NET too, but the 64 open socket limit has always caused troubled.
Theres a way to increase ( if this limit still exist ) but i dont remember.
anyway, just a guess, probably not the right one.

"A. W. Dunstan" <no@spam.thanksescreveu na mensagem
news:Nf******************************@speakeasy.ne t...
I'm creating a socket as follows:

m_networkSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
m_networkSocket.LingerState = new LingerOption(true, 1);
m_networkSocket.Blocking = true;
m_networkSocket.SetSocketOption(SocketOptionLevel. Socket,
SocketOptionName.NoDelay, true);
m_networkSocket.SetSocketOption(SocketOptionLevel. Socket,
SocketOptionName.KeepAlive, !persistentConnection);

IPEndPoint them = new IPEndPoint(IPAddress.Parse(hostname), port);
try
{
m_networkSocket.Connect(them);
Debug.Assert(m_networkSocket.Connected,
"Connect() returned but we're not connected! Socket is: " +
m_networkSocket);
}
catch (SocketException se)
{
System.Console.WriteLine("connect caught: " + se);
}

After writing (synchronously) I close it thus:

m_networkSocket.Shutdown(SocketShutdown.Send);
m_networkSocket.Disconnect(false);
m_networkSocket.Close();
m_networkSocket = null;

The design requires that I open, write & close the socket for each message
I'm sending (the network might be unreliable, so a persistent connection
won't work). The whole thing runs in a single thread, taking messages out
of a queue (other threads insert messages into the queue).

The problem I've run into is that this works fine for the first block of
messages (I've tried batches of 16, 32 and 64 messages, with messages sent
in rapid succession). This first batch always works. I let a few seconds
pass, then send another batch. Sometimes the 2nd batch works, sometimes
not. If it fails it trips on the Debug.Assert immediately after the call
to Connect().

If it's returning from Connect() without throwing anything I'd _assumed_
that the connect worked - but the failure to pass the assertion tells me
other wise!

Anybody have any ideas as to what might be going on? I'm somewhat new to
socket programming, very new to Microsoft. We're using Visual Studio 2005
on XP Pro SP2.

thanks

--
Al Dunstan, Software Engineer
OptiMetrics, Inc.
3115 Professional Drive
Ann Arbor, MI 48104-5131

Sep 10 '08 #3

P: n/a
On Tue, 09 Sep 2008 17:07:15 -0700, Fernando <Fa************@hotmail.com>
wrote:
im new to .NET too, but the 64 open socket limit has always caused
troubled.
There is no such limit. Even on Win9x, you could have hundreds of sockets
open, and the NT-based OSs go _much_ higher than that.

You may be thinking of the 64-socket limit on WSAEventSelect (due to the
underlying limit in WaitForMultipleObjects), or in the legacy function
select. But there are simple ways to code around those, and it's not a
limit on the actual number of sockets, but just how many any given thread
can watch at once.

You'll note also that the OP's issue happens with a variety of numbers of
connections per "batch", not just 64, and doesn't happen 100% of the
time. So, I think that the issue here is unrelated to any physical limit
on the number of sockets and/or connections, inasmuch as any limitation
even exists.

Pete
Sep 10 '08 #4

This discussion thread is closed

Replies have been disabled for this discussion.