TJ_Hope

Hi there,

I've a trivial piece of async socket code. However I do call Connect and BeginReceive routine on the dedicated short-living thread. After a successful connect thread dies and this cause ReceiveCallback to be called. In it EndReceive will throw SocketException with error 995: which tells that either app or thread has been finished - so i just start to receive from scratch calling BeginReceive.

Now that when the data appears on that socket ReceiveCallback is called as it should be. BUT: socket's Connected property is false!

Question is: am I missing something obvious Or do I do it wrong (connection)

Thanks. Attached you'll find a sample code to reproduce the "issue" (err, formatting is not preserved for some reason¡­).

Code Snippet

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

namespace ConsoleApplication10

{

// State object for receiving data from remote device.

public class StateObject

{

// Client socket.

public Socket workSocket = null;

// Size of receive buffer.

public const int BufferSize = 256;

// Receive buffer.

public byte[] buffer = new byte[BufferSize];

// Received data string.

public StringBuilder sb = new StringBuilder();

}

public class AsynchronousClient

{

// The port number for the remote device.

private const int port = 20005;

// ManualResetEvent instances signal completion.

private readonly ManualResetEvent connectDone = new ManualResetEvent(false);

private readonly ManualResetEvent receiveDone = new ManualResetEvent(false);

// The response from the remote device.

private String response = String.Empty;

public static Socket _client;

public void Connect()

{

// Connect to a remote device.

try

{

// Establish the remote endpoint for the socket.

// The name of the

// remote device is "host.contoso.com".

IPAddress ipAddress = Dns.GetHostAddresses("localhost")[0];

IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

// Create a TCP/IP socket.

_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

// Connect to the remote endpoint.

_client.BeginConnect(remoteEP, ConnectCallback, _client);

connectDone.WaitOne();

StartReceive();

}

catch (Exception e)

{

Console.WriteLine(e.ToString());

}

}

private void StartReceive()

{

try

{

// Receive the response from the remote device.

Receive(_client);

}

catch (Exception e)

{

Console.WriteLine(e.ToString());

}

}

private void ConnectCallback(IAsyncResult ar)

{

try

{

// Retrieve the socket from the state object.

Socket client = (Socket) ar.AsyncState;

// Complete the connection.

client.EndConnect(ar);

Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint);

// Signal that the connection has been made.

connectDone.Set();

}

catch (Exception e)

{

Console.WriteLine(e.ToString());

}

}

private void Receive(Socket client)

{

try

{

// Create the state object.

StateObject state = new StateObject();

state.workSocket = client;

Console.WriteLine(">>> Receive()");

// Begin receiving the data from the remote device.

client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);

}

catch (Exception e)

{

Console.WriteLine(e.ToString());

}

}

private void ReceiveCallback(IAsyncResult ar)

{

try

{

// Retrieve the state object and the client socket

// from the asynchronous state object.

StateObject state = (StateObject) ar.AsyncState;

Socket client = state.workSocket;

// Read data from the remote device.

int bytesRead = client.EndReceive(ar);

Console.Out.WriteLine(">>> ReceiveCallback() -- connected: " + client.Connected);

if (bytesRead > 0)

{

// There might be more data, so store the data received so far.

state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

// Get the rest of the data.

client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);

}

else

{

// All the data has arrived; put it in response.

if (state.sb.Length > 1)

{

response = state.sb.ToString();

}

// Signal that all bytes have been received.

receiveDone.Set();

Console.WriteLine(">>> ReceiveCallback() -- received: {0}", response);

}

}

catch (SocketException se)

{

if (se.ErrorCode == 995)

{

Console.Out.WriteLine(">>> error: " + se.SocketErrorCode + " : " + se.Message);

Receive(_client);

}

}

catch (Exception e)

{

Console.WriteLine(e.ToString());

}

}

}

internal class Program

{

public static int Main(String[] args)

{

Thread svr = new Thread(delegate()

{

// accept a connection

TcpListener simul = new TcpListener(Dns.GetHostAddresses("localhost")[0], 20005);

simul.Start();

Socket client = simul.AcceptSocket();

// wait here, in the meanwhile client's connect thread will finish and

// receive callback will be called - fail with err 995

Thread.Sleep(2000);

// send something to make receive callback to be called

client.Send(Encoding.ASCII.GetBytes("TEST\r\n"));

client.Send(Encoding.ASCII.GetBytes("TEST\r\n"));

client.Send(Encoding.ASCII.GetBytes("TEST\r\n"));

// wait

simul.AcceptSocket();

});

svr.Name = "Server";

svr.Start();

Thread thread = new Thread(delegate() { new AsynchronousClient().Connect(); });

thread.Name = "Connect!";

thread.Start();

Console.ReadKey();

return 0;

}

}

}



Re: .NET Framework Networking and Communication Socket.Connected == false after being connected

Quagmire

Hi TJ,

not sure what your trying to do exacly, ive only really worked with async socket stuff ( give me a few pointers as to what your trying to achieve ).

The bizarre thing with you code is that when using port 20005 the AcceptSocket function doesn't block, but using for instance port 10005 it does and behaves as it should do, very strange, try it and see.

Thanks!


Quagmire





Re: .NET Framework Networking and Communication Socket.Connected == false after being connected

TJ_Hope

Hi, Quagmire

I'm only trying to issue a Connect and BeginReceive on a separate short-living thread. AcceptSocket works as it should for me, it blocks... My issue is totally on the client side: it's like if you call Connect and BeginReceive on a thread that will die before any data comes on a socket - you'll get an exception in ReceiveCallback with number 995. Afterwards socket's Connected property is false! But the socket itself is alive, connected and receive data just fine (after issuing BeginReceive in exception handler section for exception with code 995)

The sequence is:

--> server listens on some (any) port

--> client creates a thread (ConnectThread) on which it calls Connect and then BeginReceive

<-- client's ConnectThread dies coz there's nothing to do

<-- ReceiveCallback is getting called and upon reaching EndReceive fails with SocketException, error 995: "'The I/O operation has been aborted because of either a thread exit or an application request at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)'"

<-- I do handle this by catching it and for error 995 I try to initiate async receive again by calling BeginReceive

--> server sends data (in the above code there's a slight delay between Accept and Send to simulate this behavior)
<-- ReceiveCallback is getting called because of data available, EndReceive is happy, everything is just fine, except the socket's Connected property: it's false! - means socket was never been connected WTF

I understand why it fails with an exception for the first time - it's when the thread dies. OK. What i don't understand is why the Connected property on this same socket is getting set to false...

Hope now it's more clear as to what i'm trying to do.

Thanks.





Re: .NET Framework Networking and Communication Socket.Connected == false after being connected

TJ_Hope

It only seems to happen if you issue BeginReceive on a short-living thread.