attn: MVPs... Sockets.. Killing!!

S

Slappy White

Hi All,
I have a strange problem with .net sockets (Protocol TCP/IP). I have
developed a slave application that listens for incoming connection in
asynchronous mode, and accepts incoming connection in a socket and returns
to the listening mode.

The connected socket then uses async mode to read and write from the
underlying network stream. In the AsyncRead call back function an event is
raised to handle the data received. While processing the message, If the
break the connection from my master application (which sends data), none of
the async read/send call back methods throws an exception to indicate
connection is broken.

The worst is when I send the Ack, the properties of socket indicate the
stream is connected and the async send method sends data without any
throwing exception. But, I know for sure connection is broken. This puts my
messaging processing system in soup.

The big issue for me here is that I have invested a great deal of time and
an important client's money developing this solution. I chose .Net because
of it's reputation as a cutting edge server based framework and convinced my
client this was the way to go. Now I find that the solution is unusable and
I have been let down by the .Net framework. This is a critical system and a
socket sending an acknowledgement to a non-existent connection and reporting
success is frightening in terms of the undependability of this component of
the .Net Framework.

Is there an answer to this problem? Is there a fix for what is undeniably a
massive bug in the Socket class? How can I proceed using my solution in
..Net?

Is there an alternative third party socket class (similar to winsock
control) that I can use to solve this problem?

Any help is greatly appreciated.

Thanks & Regards,
An extremely disappointed dotnet framework user.
 
S

Shakir Hussain

Slappy,

Clearly .Net framework is the improved version of all the previous
development tools. The nature of problems may differ based on implementation
and understanding of framework.

Can you paste the code of Async callback to investigate?

Worst case, you can use c++ code (if it works) either in "unsafe code
blocks" or through managed code.

Shak.
 
N

Nicholas Paldino [.NET/C# MVP]

Shakir,

It should be pointed out that unsafe C# is NOT C++ code (as was
indicated by your post).
 
S

Shakir Hussain

Hmm.....ok..accepted.

Slappy make a note of it.

Shak.


Nicholas Paldino said:
Shakir,

It should be pointed out that unsafe C# is NOT C++ code (as was
indicated by your post).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Shakir Hussain said:
Slappy,

Clearly .Net framework is the improved version of all the previous
development tools. The nature of problems may differ based on implementation
and understanding of framework.

Can you paste the code of Async callback to investigate?

Worst case, you can use c++ code (if it works) either in "unsafe code
blocks" or through managed code.

Shak.
event
is none
of puts convinced unusable
and and component
of undeniably
 
A

Alan Pretre

Slappy White said:
While processing the message, If the
break the connection from my master application (which sends data), none of
the async read/send call back methods throws an exception to indicate
connection is broken.

Hi.

The unfortunate thing about .NET Socket class is there is no event when the
connection goes down.

I have run into this problem as well. Fortunately, it is possible to write
an interop wrapper around the Winsock library in WS2_32.DLL to get Winsock
events. I am not at liberty to post my code but I can tell you these are
the routines, data structures, and defines I used to create my wrapper.
Whenever one of the Winsock events occurs, I send out a .NET event to the
subscriber. You can use WaitForSingleObject() or WaitForMultipleObjects()
to wait on Winsock events.

WSADATA
WSANETWORKEVENTS
WSAStartup()
WSACreateEvent()
WSAGetLastError()
WSACloseEvent()
WSACleanup()
WSAEventSelect()
WSAEnumNetworkEvents()
WSAResetEvent()
FD_CLOSE


One of the challenges you have in .NET is getting the HSOCKET from a .NET
Socket object. You can use reflection to get it. See

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&[email protected]

Good luck. If you look these functions up you should see what you need to
do.

-- Alan
 
S

Shakir Hussain

Slappy,

I am not good in this socket programming. However i tried this

I added Microsoft Winsock Control 6.0 (SP5) from COM objects as reference.
It created Interop.MSWinsockLib.

I was going through functions and events in object browser. I found there is
an event handler named "DMSWinsockControlEvents_ErrorEventHandler".

I also found a Enum "ErrorConstants" having atleast 30 errors.

May be you have a solution in .Net already. Have u tried this?

Shak.
 
W

William Stacey [MVP]

Can't you just use the "Handle" Property on the Socket class to get the
winsock handle?
 
W

William Stacey [MVP]

Unless I miss your problem, this is not a .Net issue, but is age old
behavior of TCP and WinSock (which .Net uses.) This and related issues have
stumped TCP programmers for years and there is not one best answer - as it
depends on your app.

Note that TCP is full-duplex. So you can close the connection half-way and
still send data on the other half (i.e. web browser sends request and closes
its half, server sends back reply and closes its side.) Also note that for
async sockets, winsock sends FD_Close when the connection drops *normally*.
However that event is never received if you just unplug the sender/client or
the sender just dies. Your TCP connection stays waiting for data because it
never receives an indication or any data for that matter, that tells it to
close. I think a timeout of 10 min may happen, not sure on that.

Options:
1) Create a command/response structure, and expect reply within n time. Use
a Timer that calls back to your delegate if async callback never resets your
timer event.
2) Add an "echo" function to protocol. Client is expected to send out
"echo" packets to server to let it know it is still there every n seconds.

These and other Winsock FAQs are documented well at below site:
http://tangentsoft.net/wskfaq/newbie.html#abnormalclose

Others you may find useful:
http://www.csharphelp.com/archives3/archive486.html
http://www.codeproject.com/csharp/XYNetSocket.asp#xx767503xx (read the
replies at the bottom)

If none of this helps, please post a small but complete code sample that
clearly shows your issue.
 
W

William Stacey [MVP]

Another solution is to use threads and use the blocking version send and
receive socket methods with timeouts if you don't have a lot of clients (
i.e. hundreds)

--
William Stacey, MVP

William Stacey said:
Unless I miss your problem, this is not a .Net issue, but is age old
behavior of TCP and WinSock (which .Net uses.) This and related issues
have
....
 
A

Alan Pretre

William Stacey said:
Can't you just use the "Handle" Property on the Socket class to get the
winsock handle?

Hi, if he is using TcpListener in his server, the
TcpListener.AcceptTcpClient() function returns a TcpClient. This class has
no *public* socket handle. The link I gave shows how to use reflection to
grab the *protected* handle.

-- Alan
 
S

Slappy White

Hi Alan,
Thanks for your kind note and sorry for my long silence. What you have
pointed out is 100% true - .NET SOCKETS/FRAMEWORK LACK THE CAPABILITY of
propogating

the error up from the winsock dll to the managed .net environment.

I was trying out in various ways to assure the problem and find a solution
to it. But I could not follow the solution suggested by you Alan. Some
sample

piece of code or a link to some website to use winsock dll strctures in .net
and Dll import calls would be of great help to me.

As pointed out by William, it is NOT the problem with the nature of the
TCP/IP design. Here are the options I tried and any suggestions / sample
code/web site link of great great help to me.


1. I have an asynchronous TCP socket (Say, slave) that listens for data from
a Master (which I don't have any control).

Design Constraints:
The Slave should not initiate any connection requests/ send other messages
EXCEPT the acknowledgement for the incoming messages from master, at all
times.

And the slave should not look for any response from the master for the
acknowledgement it sends.



The Master polls for the connection and I accept connection in a thread
like,

// Create a new TCPListner Slave and start it up
m_pTcpListener = new
TcpListener(Dns.Resolve(IpAddress).AddressList[0],Port);
m_pTcpListener.Start();


Socket pClientSocket = null;
// Inside the thread loop - If a client connects, accept the connection
pClientSocket = m_pTcpListener.AcceptSocket();


*The incoming connection is accepted and the listener keeps listening for
incoming connection in its thread.
Accepting Connection, Receiving Data all works fine. Here are the methods
for receiving data,

/// <summary> Wait for a message to arrive </summary>
public void Receive()
{
if ((m_pNetworkStream != null) && (m_pNetworkStream.CanRead))
{
// Issue an asynchronous read
m_pNetworkStream.BeginRead(m_bytRawBuffer, 0, m_iSizeOfRawBuffer,
m_pCallbackReadMethod, null);
}
else
throw new Exception("Socket Closed");
}

/// <summary>Called when a message arrives</summary>
/// <param name="ar">An async result interface</param>
private void ReceiveComplete(IAsyncResult ar)
{
try
{
// Is the Network Stream object valid
if (m_pNetworkStream.CanRead)
{
// Read the current bytes from the stream buffer
int iBytesRecieved = m_pNetworkStream.EndRead(ar);
// If there are bytes to process else the connection is lost
if (iBytesRecieved > 0)
{
try
{
string RawData =
System.Text.Encoding.ASCII.GetString(m_bytRawBuffer,0,iBytesRecieved);

// A message came in send it to the MessageHandler
this.SocketStateHandler(SocketStatus.DataReceived,RawData);
}
catch
{
}
// Wait for a new message
Receive();
}
else
throw new Exception("Shut Down");
}
}
catch (Exception ex)
{
try
{
// The connection must have dropped call the CloseHandler
this.SocketStateHandler(SocketStatus.ConnectionBroken,ex.Message);
}
catch
{
}
// Dispose of the class
Dispose();
}
}

*After parsing data, Acknowledgement message need to be sent to the Master.
I put a break point in the start of the send method and shutdown my Master

application completely to ensure it does not exist. Then, if I run through
the code, the send method sends the acknowledgement without throwing any
exception

as if the connection exists and everything is fine. This is a potential bug
in the .net sockets framework.

/// <summary>Send a raw buffer to the server</summary>
/// <param name="pRawBuffer">A Raw buffer of bytes to send</param>
public void Send(Byte[] pRawBuffer)
{
if ((m_pNetworkStream != null) && (m_pNetworkStream.CanWrite))
{
// Issue an asynchronus write
m_pNetworkStream.BeginWrite(pRawBuffer, 0, pRawBuffer.GetLength(0),
m_pCallbackWriteMethod, null);

}
else
throw new Exception("Socket Closed");
}


/// <summary>Called when a message is sent</summary>
/// <param name="ar">n async result interface</param>
private void SendComplete(IAsyncResult ar)
{
try
{
// Is the Network Stream object valid
if (m_pNetworkStream.CanWrite)
m_pNetworkStream.EndWrite(ar);
}
catch (Exception ex)
{
//Connection Error
this.SocketStateHandler(SocketStatus.ConnectionBroken,ex.Message);
}
}


*Nowhere exception is thrown and how to sovle this?



2. A VB6 application downloaded from the internet uses winsock's "Select"
function to ensure the socket is readable and it works fine in conjunction
with the

master application. It detects immediately when I break the connection/close
the master application. So, I tried making a direct call to "select"
function of

winsock dll as follows, (unfortunately it did not work in the .net)


[DllImport("ws2_32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
internal static extern int select([In] int ignoredParameter, [In] out fd_set
readfds, [In] out fd_set writefds, [In] out fd_set exceptfds, [In] IntPtr

nullTimeout);


[StructLayout(LayoutKind.Sequential)]
public struct fd_set
{
public int fd_count;
public int[] fd_array; //array of sockets
}



//make a call with sockets
fd_set SocWrite = new fd_set();
SocWrite.fd_count = 1;
SocWrite.fd_array[1] = socket.handle; //Inptr socket.handle property.
int i =
select(System.IntPtr.Zero,SockRead,SocWrite,SockError,System.IntPtr.Zero);


* Even this is not working but the call to "select" works within the VB6
Application. Am I doing something wrong here?



3. The final option Iam going to try is make an VB6 dll and try to call that
dll from .net. But I dont know how to get the long handle required by the VB

call to the dll.

Please throw some light and help me to get out of this problem. Further, I
don't have any idea about getting the winsock events and it would be great
if you could explain or provide a link to that.
Thanks a lot for your time.
 
S

Slappy White

Hi William,
Thanks a lot for your suggestions. Please see the posting under Alan's
thread and guide me with your views.
 
M

Mike Blake-Knox

What you have
pointed out is 100% true - .NET SOCKETS/FRAMEWORK LACK THE CAPABILITY of
propogating

the error up from the winsock dll to the managed .net environment

Does this occur every time a socket is disconnected or are some disconnects
detected? As Alan pointed out, the "normal" way you find out about a
disconnect is when you find 0 bytes are read.

Can you post a standalone version of your test program "slave" (server?)
and a matching client? Also, it would be a good idea for it to print
something from each of your catch blocks to make it easier to see what's
going on.

Mike
 
A

Alan Pretre

Slappy White said:
Hi Alan,
Thanks for your kind note and sorry for my long silence. What you have
pointed out is 100% true - .NET SOCKETS/FRAMEWORK LACK THE CAPABILITY of
propogating the error up from the winsock dll to the managed .net environment.

I was trying out in various ways to assure the problem and find a solution
to it. But I could not follow the solution suggested by you Alan. Some
sample piece of code or a link to some website to use winsock dll strctures in .net
and Dll import calls would be of great help to me.

Hi. The underlying winsock library supports native operating system events
(not to be confused with .NET events).

To get started look at WSACreateEvent() in the Platform SDK, then start
googling. The particular event type you are interested in is FD_CLOSE (see
WSAEventSelect()). You will find various examples of source out there, some
in C and some in VB 6 even. Ironically, the VB 6 code is probably the
easiest to translate into C# p/invoke. You can find a very helpful VB 6
module at http://www.thevbzone.com/modWINSOCK.bas. This has all the
constants and function signatures defined, etc.

Winsock Functions:
http://msdn.microsoft.com/library/d...y/en-us/winsock/winsock/winsock_functions.asp

WSACreateEvent():
http://msdn.microsoft.com/library/d...ry/en-us/winsock/winsock/wsacreateevent_2.asp

WSAEventSelect():
http://msdn.microsoft.com/library/d...ry/en-us/winsock/winsock/wsaeventselect_2.asp

pinvoke.net is usually a great place to go to for p/invoke signatures, but
surprisingly, has none for winsock at this time.
http://pinvoke.net/

Example to create multiple (operating system) events and wait on them:
http://msdn.microsoft.com/library/d...dllproc/base/waiting_for_multiple_objects.asp


-- Alan
 
S

Slappy White

Hi Alan,
Thanks a lot for your directions. Will try it out this week and let you
know the progress soon..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top