public bool Connect (string address, int remotePort)
{
if (_socket != null && _socket.Connected)
return true;
IPHostEntry hostEntry = Dns.GetHostEntry (address);
foreach (IPAddress ip in hostEntry.AddressList) {
try {
IPEndPoint ipe = new IPEndPoint (ip, remotePort);
_socket = new Socket (ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
break;
} catch (System.Exception e) {
PushPacket ((ushort)MsgIds.Id.CONNECTION_ATTEMPT_FAILED, e.Message);
return false;
}
}
return true;
}
void ConnectionCallback (System.IAsyncResult ar)
{
NetBitStream stream = new NetBitStream ();
stream._socket = (Socket)ar.AsyncState;
try {
_socket.EndConnect (ar);
_socket.SendTimeout = _sendTimeout;
_socket.ReceiveTimeout = _revTimeout;
PushPacket ((ushort)MsgIds.Id.CONNECTION_REQUEST_ACCEPTED, "");
_socket.BeginReceive (stream.BYTES, 0, NetBitStream.HEADER_LENGTH, SocketFlags.None, new System.AsyncCallback (ReceiveHeader), stream);
} catch (System.Exception e) {
if (e.GetType () == typeof(SocketException)) {
if (((SocketException)e).SocketErrorCode == SocketError.ConnectionRefused) {
PushPacket ((ushort)MsgIds.Id.CONNECTION_ATTEMPT_FAILED, e.Message);
} else
PushPacket ((ushort)MsgIds.Id.CONNECTION_LOST, e.Message);
}
Disconnect (0);
}
}
Here are two functions. When I call
client.Connect ("127.0.0.1", 10001);
It just steps over the break;
after
_socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
and goes to return true;
. I set a breakpoint at ConnectionCallback but it does not go into this function.
There is no server listening on the 10001
port.
So I think it at least should throw an exception (connect failed), then go into the catch
.
Or have I made a mistake in the two functions?
Here is a Minimal, Complete, and Verifiable example
using System;
using System.Net.Sockets;
using System.Net;
namespace TestSocket
{
class MainClass
{
public static void Main (string[] args)
{
NetTCPClient tcp_client = new NetTCPClient ();
tcp_client.Connect ("127.0.0.1", 10001);
}
}
class NetTCPClient
{
Socket _socket = null;
public bool Connect (string address, int remote_port)
{
if (_socket != null && _socket.Connected)
return true;
IPHostEntry host_entry = Dns.GetHostEntry (address);
foreach (IPAddress ip in host_entry.AddressList) {
try {
IPEndPoint ipe = new IPEndPoint (ip, remote_port);
_socket = new Socket (ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult ia = _socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
break;
} catch (Exception e) {
Console.WriteLine ("Connet() catch an exception!");
return false;
}
}
return true;
}
void ConnectionCallback (System.IAsyncResult ar)
{
Console.WriteLine ("ConnectionCallback() ");
}
}
}
I think you may have misunderstood what BeginConnect
does. That doesn't make the connection - it just starts making the connection, asynchronously. So yes, I'm not at all surprised that "step over" immediately steps to the next statement - that's working as intended.
However, I would have expected that a breakpoint in ConnectionCallback
would be hit - that's what you should concentrate on as a problem. That's also where you should put the exception handling, as that's where any problems with making the connection would be found.
Alternatively, if you're using C# 5 or higher, you should look into using async/await, which would allow you to get rid of all the callbacks. Then you'll get a much more familiar experience when debugging - if you step over that line, it really will be connected (or there'll be a failure) by the time you hit the next line. Just be aware that other things may happen (even on the same thread) while it's "awaiting" the response.
Unfortunately, I can't see anything in Socket
which implements the relevant pattern. You could use TaskFactory.FromAsync
to adapt the "old" style to the "new" style, but it's likely to be fairly painful.
Another approach is to try to move to higher-level constructs like TcpClient
instead of the lower-level Socket
class.
See more on this question at Stackoverflow