Hi Jason,
Thanks for your kind note and sorry for my long silence. .NET
SOCKETS/FRAMEWORK LACK THE CAPABILITY of propogating the error up from the
winsock dll to the managed .net environment.
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.
Thanks & Regards,
Senthil.
> if you drop some reproducible code here it would be easier to help you as i
> don't always have the time to knock out an example
[quoted text clipped - 46 lines]
> > Thanks & Regards,
> > An extremely disappointed dotnet framework user.