473,378 Members | 1,078 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Sockets and non-blocking connect

Hi,

I'm using a non-blocking connect to connect to a server.
Works fine -- the server gets and accepts the connection.
However, once the connection is established, I cannot
retrieve either the local or the remote endpoint from
the client-side socket.

The *really* strange thing is that Socket.LocalEndPoint is null.
According to the doc, that's impossible: reading the LocalEndPoint
or RemoteEndPoint property should either throw an exception or
give me a proper endpoint.

I've attached two very simple code snippets below. The server
simply sits and waits for an incoming connection on port 12345
on localhost. Once it has accepted an incoming connection, the
server sleeps for 10 seconds and then exits.

On the client side, I put the socket in non-blocking mode, initiate
the connection, and then use poll to wait for the socket descriptor
to become writeable (which indicates the the connection was completed).
At that point, LocalEndPoint and RemoteEndPoint are null, even though
the connection was successfully established (as evidenced by the output
from the server).

To run this, start the server in a window and the client in another window.

This looks like a bug in the .NET socket implementation to me. (The
equivalent code in C++ works fine.)

Can anyone help me out with this?

Thanks,

Michi.
using System;
using System.Net;
using System.Net.Sockets;

class Server
{
static void Main(string[] args)
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

s.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345));
s.Listen(1);
Socket c = s.Accept(); // Blocks until we get an incoming connection
Console.WriteLine((IPEndPoint)c.LocalEndPoint);
Console.WriteLine((IPEndPoint)c.RemoteEndPoint);
System.Threading.Thread.Sleep(10000);
}
}
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;

class Client
{
static void Main(string[] args)
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

s.Blocking = false; // We want to use non-blocking connect

try
{
s.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345)); // Initiate connection
}
catch (Win32Exception ex)
{
if (ex.ErrorCode == 10035) // WSAEWOULDBLOCK is expected, means connect is in progress
{
bool ready;
int repeatCount = 3;
do
{
ready = s.Poll(1000000, SelectMode.SelectWrite); // Wait until connection is complete
} while (!ready && --repeatCount > 0);
if (!ready)
{
Console.WriteLine("Connect failed");
Environment.Exit(1);
}
}
else
{
Console.WriteLine(ex);
Environment.Exit(1);
}
}
catch (System.Exception ex)
{
Console.WriteLine(ex);
Environment.Exit(1);
}
IPEndPoint lep = (IPEndPoint)s.LocalEndPoint;
Debug.Assert(lep != null); // Assertion fails!!!

IPEndPoint rep = (IPEndPoint)s.RemoteEndPoint;
Debug.Assert(rep != null); // Assertion fails!!!

Environment.Exit(0);
}
}

Nov 15 '05 #1
7 17354
Michi Henning wrote:
This looks like a bug in the .NET socket implementation to me. (The
equivalent code in C++ works fine.)


I'm quite sure that this is a bug in the implementation of the Socket
class because I can get things to work by stepping down to the native API
with platform invoke.

Add the following definitions to the client:

[StructLayout(LayoutKind.Sequential)]
private struct in_addr
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public byte[] sin_addr;
}

[StructLayout(LayoutKind.Sequential)]
private struct sockaddr
{
public short sin_family;
public ushort sin_port;
public in_addr sin_addr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
public byte[] sin_zero;
}

[DllImport("wsock32.dll")]
private static extern int getsockname(IntPtr s, ref sockaddr name, ref int namelen);

[DllImport("wsock32.dll")]
private static extern int getpeername(IntPtr s, ref sockaddr name, ref int namelen);

[DllImport("ws2_32.dll")]
private static extern IntPtr inet_ntoa(in_addr a);

[DllImport("ws2_32.dll")]
private static extern ushort ntohs(ushort netshort);

Then, at the end of the client, instead of reading the LocalEndPoint
and RemoteEndPonit properties, insert the following:

IntPtr socket = s.Handle;
sockaddr addr = new sockaddr();
int addrLen = 16;

getsockname(socket, ref addr, ref addrLen);
IntPtr str = inet_ntoa(addr.sin_addr);
Console.WriteLine(Marshal.PtrToStringAnsi(str) + ":" + ntohs(addr.sin_port));

getpeername(socket, ref addr, ref addrLen);
IntPtr str = inet_ntoa(addr.sin_addr);
Console.WriteLine(Marshal.PtrToStringAnsi(str) + ":" + ntohs(addr.sin_port));

This correctly prints the IP address and port number of the local and remote endpoint.
Cheers,

Michi.

Nov 15 '05 #2
Michi Henning <mi***@zeroc.com> wrote in message news:<#I**************@TK2MSFTNGP09.phx.gbl>...
Hi,

I'm using a non-blocking connect to connect to a server.
Works fine -- the server gets and accepts the connection.
However, once the connection is established, I cannot
retrieve either the local or the remote endpoint from
the client-side socket.


Michi -

The reason you can not retrieve the local or remote endpoints is
because there is no connection. When the socket is set to
non-blocking, the Connect() method throws a SocketException (only for
TCP connections), since the connection can not be established without
blocking. From the Socket class library page:

"The Connect method will block, unless you specifically set the
Blocking property to false prior to calling Connect. If you are using
a connection-oriented protocol like TCP and you do disable blocking,
Connect will throw a SocketException because it needs time to make the
connection."

Thus the connection is never established, and the local and remote
endpoint values are not set. If you do not set the Blocking property
to false, your code works fine.

If you do not want to block on the Connect(), try using the async
BeginConnect() version instead. Hope this helps shed some light on
your problem.

Rich Blum - Author
"C# Network Programming" (Sybex)
http://www.sybex.com/sybexbooks.nsf/Booklist/4176
"Network Performance Open Source Toolkit" (Wiley)
http://www.wiley.com/WileyCDA/WileyT...471433012.html
Nov 15 '05 #3
"Rich Blum" <ri*******@juno.com> wrote in message
news:cc**************************@posting.google.c om...
The reason you can not retrieve the local or remote endpoints is
because there is no connection.
No.
When the socket is set to
non-blocking, the Connect() method throws a SocketException (only for
TCP connections), since the connection can not be established without
blocking. From the Socket class library page:

"The Connect method will block, unless you specifically set the
Blocking property to false prior to calling Connect. If you are using
a connection-oriented protocol like TCP and you do disable blocking,
Connect will throw a SocketException because it needs time to make the
connection."
Right. The man page says that. It also says that, if I connect in non-blocking
mode, the connection attempt is initiated, and that I should use poll() to
check
when the connection is established. Look at the code I sent -- it uses poll()
after the initial call to Connect() to wait until the socket becomes ready
for writing, which it does.
Thus the connection is never established, and the local and remote
endpoint values are not set.
No. The connection is indeed established. If you actually run the code I sent,
you will see the server receiving the incoming connection request
and correctly printing the local and remote endpoint.
If you do not set the Blocking property
to false, your code works fine.
Yes, but it also should work in non-blocking mode.

Have a look at my follow-up post. By using the native getsockname()
and getpeername() calls via platform invoke, the very same example
works just fine. The problem is definitely in the .NET Socket class
implementation.
If you do not want to block on the Connect(), try using the async
BeginConnect() version instead. Hope this helps shed some light on
your problem.


I considered that, but it doesn't solve my problem. What I need is the
connection attempt to be aborted after a set amount of time, not a
connection attempt that may block indefinitely (and tie up another
thread in the bargain).

Cheers,

Michi.

--
Michi Henning Ph: +61 4 1118-2700
ZeroC, Inc. http://www.zeroc.com

Nov 15 '05 #4
Hi!

This seems to be a bug in the framework, and I am following up with our
developers on this. However, I had a question for you. Why are you doing a
non-blocking connect and polling for the connect to succeed ? WHy dont you
use a BeginConnect./EndConnect() async pattern, and that will avoid this
issue totally.

feroze.

--
Remove "user" from the email address to reply to the author.

This posting is provided "AS IS" with no warranties, and confers no rights

Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


"Michi Henning" <mi***@triodia.com> wrote in message
news:eA**************@TK2MSFTNGP11.phx.gbl...
"Rich Blum" <ri*******@juno.com> wrote in message
news:cc**************************@posting.google.c om...
The reason you can not retrieve the local or remote endpoints is
because there is no connection.
No.
When the socket is set to
non-blocking, the Connect() method throws a SocketException (only for
TCP connections), since the connection can not be established without
blocking. From the Socket class library page:

"The Connect method will block, unless you specifically set the
Blocking property to false prior to calling Connect. If you are using
a connection-oriented protocol like TCP and you do disable blocking,
Connect will throw a SocketException because it needs time to make the
connection."


Right. The man page says that. It also says that, if I connect in

non-blocking mode, the connection attempt is initiated, and that I should use poll() to
check
when the connection is established. Look at the code I sent -- it uses poll() after the initial call to Connect() to wait until the socket becomes ready
for writing, which it does.
Thus the connection is never established, and the local and remote
endpoint values are not set.
No. The connection is indeed established. If you actually run the code I

sent, you will see the server receiving the incoming connection request
and correctly printing the local and remote endpoint.
If you do not set the Blocking property
to false, your code works fine.


Yes, but it also should work in non-blocking mode.

Have a look at my follow-up post. By using the native getsockname()
and getpeername() calls via platform invoke, the very same example
works just fine. The problem is definitely in the .NET Socket class
implementation.
If you do not want to block on the Connect(), try using the async
BeginConnect() version instead. Hope this helps shed some light on
your problem.


I considered that, but it doesn't solve my problem. What I need is the
connection attempt to be aborted after a set amount of time, not a
connection attempt that may block indefinitely (and tie up another
thread in the bargain).

Cheers,

Michi.

--
Michi Henning Ph: +61 4 1118-2700
ZeroC, Inc. http://www.zeroc.com

Nov 15 '05 #5
Feroze [MSFT] wrote:
Hi!

This seems to be a bug in the framework, and I am following up with our
developers on this. However, I had a question for you. Why are you doing a
non-blocking connect and polling for the connect to succeed ? WHy dont you
use a BeginConnect./EndConnect() async pattern, and that will avoid this
issue totally.


BeginConnect()/EndConnect() have two problems:

- They tie up a thread for the duration of the connection attempt (which
may take quite a while).

- There is no way to adjust the timeout for the connection.

I'm in a situation where I want to establish a connection and
wait for a specified time for the attempt to succeed.
Even assuming that I could set a timeout for BeginConnect()
(which I can't), the async pattern then forces me to suspend
the calling thread after calling BeginConnect() and then wake up that
thread again from within the callback when it finally arrives.
That's a lot of hoops to jump through just to wait for a set amount of
time and also wastes an additional thread.

The code is a lot clearer if it stays all in one thread:

- put socket in non-blocking mode

- call Connect()

- catch SocketException and test for WSAEWOULDBLOCK

- call Select() with timeout

- Select() either times out or indicates that the connection was established

- if timeout, return error

- else get local and remote endpoint

Cheers,

Michi.

Nov 15 '05 #6
Michi Henning <mi***@zeroc.com> wrote in news:40**************@zeroc.com:
- They tie up a thread for the duration of the connection attempt (which
may take quite a while).

- There is no way to adjust the timeout for the connection.
Use a secondary thread to do the connect. Thats what Indy has an option to
do.

I'm in a situation where I want to establish a connection and
wait for a specified time for the attempt to succeed.
Even assuming that I could set a timeout for BeginConnect()
(which I can't), the async pattern then forces me to suspend
the calling thread after calling BeginConnect() and then wake up that
thread again from within the callback when it finally arrives.
That's a lot of hoops to jump through just to wait for a set amount of
time and also wastes an additional thread.

The code is a lot clearer if it stays all in one thread:

- put socket in non-blocking mode

- call Connect()

- catch SocketException and test for WSAEWOULDBLOCK

- call Select() with timeout

- Select() either times out or indicates that the connection was
established

- if timeout, return error

- else get local and remote endpoint

Cheers,

Michi.


--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"
ELKNews - Get your free copy at http://www.atozedsoftware.com

Nov 15 '05 #7
Thanks a lot for this information. We appreciate the information your
provided for this issue. I will follow up with the developers.

Thanks a lot for reporting this bug.

feroze
-----------
This posting is provided as is, without warranties, and confers no
rights.

Michi Henning <mi***@zeroc.com> wrote in message news:<40**************@zeroc.com>...
Feroze [MSFT] wrote:
Hi!

This seems to be a bug in the framework, and I am following up with our
developers on this. However, I had a question for you. Why are you doing a
non-blocking connect and polling for the connect to succeed ? WHy dont you
use a BeginConnect./EndConnect() async pattern, and that will avoid this
issue totally.


BeginConnect()/EndConnect() have two problems:

- They tie up a thread for the duration of the connection attempt (which
may take quite a while).

- There is no way to adjust the timeout for the connection.

I'm in a situation where I want to establish a connection and
wait for a specified time for the attempt to succeed.
Even assuming that I could set a timeout for BeginConnect()
(which I can't), the async pattern then forces me to suspend
the calling thread after calling BeginConnect() and then wake up that
thread again from within the callback when it finally arrives.
That's a lot of hoops to jump through just to wait for a set amount of
time and also wastes an additional thread.

The code is a lot clearer if it stays all in one thread:

- put socket in non-blocking mode

- call Connect()

- catch SocketException and test for WSAEWOULDBLOCK

- call Select() with timeout

- Select() either times out or indicates that the connection was established

- if timeout, return error

- else get local and remote endpoint

Cheers,

Michi.

Nov 15 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: DBenson | last post by:
So far I've been unable to find anything that addresses this one... Basically, if I am logged in as root and issue a "php -m", mysql is in the list of installed modules. If I log in or su to a...
15
by: kernel.lover | last post by:
Hello, i want to know to have multiple clients connects to same server program does following is correct code #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include...
6
by: Ted | last post by:
Hello all, Please could somebody with a little time on their hands help me with my net sockets program? The aim is to send multiple transactions via C# network stream and read them back. The...
4
by: BadOmen | last post by:
Hi, What is the different between 'System.Net.Sockets.Socket' and 'System.Net.Sockets.TcpClient'? When do I use System.Net.Sockets.TcpClient and System.Net.Sockets.Socket?? Yours, Jonas
4
by: Robert McNally | last post by:
Hello, I'm currently learning c# and have been trying to write a simple program with sockets. The problem is i'm trying to send an email with an attachment, (which is the program itself) by...
1
by: John Smith | last post by:
How to find generlly "Secure Sockets Layer (SSL)" version for a given page? Not through program. John
7
by: Steven | last post by:
Hi, Thanks all for you help with my "socket and buffer size" question. I have decided to use async ones, and my code is working pretty well. But i still have a non-answered question: Is it...
7
by: D. Patrick | last post by:
I need to duplicate the functionality of a java applet, and how it connects to a remote server. But, I don't have the protocol information or the java source code which was written years ago. ...
4
by: Greg Young | last post by:
Ok so I think everyone can agree that creating buffers on the fly in an async socket server is bad ... there is alot of literature available on the problems this will cause with the heap. I am...
0
by: rossabri | last post by:
This topic has been addressed in limited detail in other threads: "sockets don't play nice with new style classes :(" May 14 2005....
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.