Weird C# SocketException - c#

While testing my Client-Server program, I encountered a weird exception when trying to connect to the server on a different router:
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond."
The client can connect to the server perfectly in the local network, however it doesn't work when it is over the internet.
I port forwarded port 1250 (the one I'm using), and using SimplePortForwarding (http://www.simpleportforwarding.com/) I verified that the port was open and working.
I based my implementation on this tutorial:
http://www.developerfusion.com/article/3918/socket-programming-in-c-part-1/
Any idea what is wrong?
Thanks!
Here is the server listen method:
public void startListening(int port)
{
lock(_locker)
{
_listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
// Bind socket to local endpoint, and listen for incoming connections
IPEndPoint ipEndpoint = new IPEndPoint(IPAddress.Any, port);
_listeningSocket.Bind(ipEndpoint);
_listeningSocket.Listen(10);
waitForNewClient();
// successfully started listening
_isListening = true;
} catch (SocketException e)
{
// failed for some strange reason
_isListening = false;
}
}
}
Here is the client connect code:
public String connect(String ipAddress, int port)
{
lock(_locker)
{
if (!_connecting)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
try
{
_socket.Connect(endpoint);
_connected = true;
waitForData();
_eventManager.queueEvent(new PlayerJoinedEvent(PlayerJoinedEvent.PLAYER_JOINED, name));
} catch (SocketException e)
{
// Exception is thrown HERE
return e.Message;
}
}
}
return "";
}

Make it sure that your Server IP address is public unless it is not reachable.
Check this link for private address spaces.

You opened port 1250 on the server or the client router? It needs to be opened on the server router. You may need to make sure your server is connected to your DMZ port and/or have DMZ enabled on your server router.
Hope this helps.

I Fixed the problem.
The IP Address I used was the internal ip address I got from ipconfig, but the IP address I needed to use was the external one, the one you get from services like http://www.whatsmyip.org/.
I'm still confused as to why these two numbers are different.

Related

c # punch NAT network with TCP / IP protocol

Punching the UDP network works and works. However, when it comes to TCP, it's possible that I'm writing something wrong but I'm not a beginner programmer, or maybe I don't understand something.
Of course, I'll shorten a bit, we assume that we already have something as trivial as connection to an external server :)
Packet synchronization between threads as well as their creation, queuing, serialization, sending raw bytes and much more I skip because it is about the element of creating TCP sockets and not what works.
We will use the TcpListener class for the server.
public void InitializeServer(IPAddress address, int port)
{
try
{
// 127.0.0.1 accept only local connections, 0.0.0.0 is open for whole internet connections
listener = new TcpListener(address, port);
socket = listener.Server;
// Enable NAT Translation
listener.AllowNatTraversal(true);
// Start listening for example 10 client requests.
listener.Start(listenQueue);
Debug.Log($"[L{socket.LocalEndPoint}]Server start... ", EDebugLvl.Log);
OnServerInitialize(true);
// Enter the listening loop.
StartListener();
}
catch (SocketException e)
{
Debug.LogError($"SocketException: {e}", EDebugLvl.Error);
OnServerInitialize(false);
}
}
We start listening
private void StartListener()
{
Debug.Log("\nWaiting for a connection... ");
listener.BeginAcceptTcpClient(AcceptCallback, listener);
}
When the server receives the connection, we create a new socket
private void AcceptCallback(IAsyncResult ar)
{
TcpListener server = (TcpListener)ar.AsyncState;
TcpClient newClient = null;
try
{
newClient = server.EndAcceptTcpClient(ar);
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
if (newClient != null && newClient.Connected)
{
//...
client.StartRead();
}
//Loop
StartListener();
}
We create a new socket at the client and try to establish a connection
public void Connect(IPEndPoint remote, IPEndPoint bind = null, bool reuseAddress = false)
{
if (bind == null)
{
client = new TcpClient();
}
else
{
client = new TcpClient(bind);
}
socket = client.Client;
if (reuseAddress)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
//It throws me a error SocketOption so im comment this.
//socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, reuseAddress);
}
client.BeginConnect(remote.Address, remote.Port, ConnectCallback, null);
}
The connection works without any problems and data transfer.
Unfortunately, here as we know, we must start a new socket listening on the same address and port that was created when connecting to the server. I do this for every client.
public void StartHost(Client server)
{
if (server != null && server.socket.Connected)
{
IPEndPoint localHost = (IPEndPoint)server.socket.LocalEndPoint;
InitializeHost(localHost.Address, localHost.Port);
}
}
public void InitializeHost(IPAddress address, int port, bool reuse = false)
{
try
{
listener = new TcpListener(address, port);
socket = listener.Server;
if (reuse)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
}
// Enable NAT Translation
listener.AllowNatTraversal(true);
// Start listening for example 10 client requests.
listener.Start(listenQueue);
Debug.Log($"\n[L{socket.LocalEndPoint}]Host start... ", EDebugLvl.Log);
OnServerInitialize(true);
// Enter the listening loop.
StartListener();
}
catch (SocketException e)
{
Debug.LogError($"SocketException: {e}", EDebugLvl.Error);
OnServerInitialize(false);
}
}
private void StartListener()
{
Debug.Log("\nWaiting for a connection... ");
listener.BeginAcceptTcpClient(AcceptCallback, listener);
}
private void AcceptCallback(IAsyncResult ar)
{
TcpListener server = (TcpListener)ar.AsyncState;
TcpClient newClient = null;
try
{
newClient = server.EndAcceptTcpClient(ar);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
if (newClient != null && newClient.Connected)
{
//...
client.StartRead();
}
//Loop
StartListener();
}
So, as they write everywhere ... client "B" sends a packet to the server that wants to establish a connection, the server sends information to the client "A" about the client "B" and vice versa
Then they both try to connect with the new socket? No problem...
public void Connect(IPEndPoint remote, IPEndPoint bind = null, bool reuseAddress = false)
{
if (bind == null)
{
client = new TcpClient();
}
else
{
client = new TcpClient(bind);
}
socket = client.Client;
if (reuseAddress)
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
//socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, reuseAddress);
}
client.BeginConnect(remote.Address, remote.Port, ConnectCallback, null);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
client.EndConnect(ar);
}
catch (Exception e)
{
Debug.LogError(e.ToString(), EDebugLvl.ConnectionError);
}
if (client.Connected)
{
Debug.Log($"[P{socket.RemoteEndPoint}, L{socket.LocalEndPoint}]Connected", EDebugLvl.ConnectionLog);
stream = new NetworkStream(socket, FileAccess.ReadWrite, true);
StartRead();
}
ConnectedComplete(this, socket.Connected);
}
No matter how many times I try, the connection is rejected ... the addresses match everywhere and yet it does not work, so I have nothing to write about in this case, especially since UDP works for me.
What I wrote only works on the same NAT network. Unfortunately, I noticed that on the same NAT created two connections. One is the result of trying to connect the new socket A to B and the other is the result of receiving a new connection from B to A, so each client has one unnecessary socket connected by a local address. So all NAT TCP / IP Punch NAT doesn't work for me. I can actually use UDP but I really need TCP. I have been sitting on it for several months in my free time but nowhere can I find an example from the code and not the theory of which there is a lot.
I accumulated a lot of knowledge for 8 years and from 2 I write applications using sockets and finally I need to punch the net.
Why won't I use the ready solution? I need my own which is fully open using only UDP and TCP because some target devices only support these protocols. I also used the Socket class but this one did not give me a working copy.
Maybe someone will be able to help me for which I would be very grateful and certainly the post will also help others understand this.
Regards
Octavian
NAT hole punching only works with UDP, and even that is a hack.
NAT firewall implementations will start tracking a TCP stream when they see the initial SYN packet leaving the network. To capture incoming TCP streams you need to create an incoming rule on the router, there's no way around this. If the router supports UPnP, you can ask it to create that rule for you dynamically.
Since UDP doesn't have a SYN packet equivalent, routers will start tracking the stream on any outgoing packet. This is why NAT hole punching works. If both end points are behind NAT and just assume that the link will work. Both can just start sending UDP packets to each other. The routers will add the connection state, and map the incoming packets to each endpoint.

TcpListener & Socket connection fails

My friend runs a simple C# Console Application that starts a TcpListener on Port 8484. This is how it's being done:
public static void Listen()
{
Listener = new TcpListener(IPAddress.Any, 8484);
Listener.Start();
Listener.BeginAcceptSocket(new AsyncCallback(EndAccept), null);
}
public static void EndAccept(IAsyncResult IAR)
{
Console.WriteLine("Connection accepted on Port 8484.");
Socket socket = Listener.EndAcceptSocket(IAR);
Instance = new Client(socket);
Listener.Stop();
Listener = null;
}
I connect to him using:
public void Connect()
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
_socket.Connect(IP, Port);
Debug.WriteLine("Connected with server!");
}
catch (Exception ex)
{
Debug.WriteLine(TypeName + " [ERROR] Could not connect to server # {0}:{1}: {2}", IP, Port, ex.Message);
}
}
However, for some reason - he can't accept the connection, it says it doesn't respond. Port 8484 is 100% opened at his computer.
Why does this happen?
Use telnet to verify connectivity to the remote server. E.g. run the command "telnet ip_address port". If it successfully connects then you can reach the server. If telnet cannot connect then you cannot reach the server, likely due to a firewall issue.
Try disabling the firewall.1
1 - Helped user in chat to test for firewall problems, and it has not open. That has the problem

Socket.RemoteEndPoint returns gateway address

For some reason the C# socket.RemoteEndPoint started returning the address of the default gateway. It used to work and I know the code hasn't changed. I'm not sure when it started occurring as the logs don't go back far enough so I'm not sure what could have happened to this server to cause this. Everything seems to be working normally. Just not getting the remote IP anymore.
Anyone have any idea what could cause this?
Here is the relevant code.
public void startClientListening(string ipString, int port)
{
IPAddress ip = IPAddress.Parse(ipString);
// Create the listening socket...
clientListenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(ip, port);
// Bind to local IP Address...
clientListenerSocket.Bind(ipLocal);
// Start listening...
clientListenerSocket.Listen(32);
// Create the call back for any client connections...
clientListenerSocket.BeginAccept(onClientConnect, clientListenerSocket);
}
private void onClientConnect(IAsyncResult asyn)
{
Socket workerSocket = clientListenerSocket.EndAccept(asyn);
workerSocket.NoDelay = true;
//This returns 192.168.1.1 rather than the remoteIp
string remoteIp = ((IPEndPoint)workerSocket.RemoteEndPoint).Address.ToString();
}
This could happen if the default gateway was a router/ip firewall before but now it is a proxy/application firewall.
In this case the ip connection is instantiated by the proxy and therefore you see the ip address of the proxy and not of the real client.

Why is C# triggering a Socket Timeout issue on another machine?

I ran an application on my machine and it ran fine; I then run the apoplication on another machine but I'm getting a socket timeout isse connecting to the box even though Pinging works fine. Below is my socket connection Logic:
private bool openConnection(out IPEndPoint connection_Point)
{
bool connected = false;
connection_Point = new IPEndPoint(m_address, m_port);
m_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
try
{
m_sock.Connect(connection_Point);
connected = true;
}//end of try logic
catch (SocketException err)
{
connected = false;
connection_Point = null;
MessageBox.Show("Socket Exception thrown: " + err);
}
return connected;
}
ping will only tell if the IP address responds to pings. To confirm that a TCP socket can be opened, try telnet on the listening port from the new machine. If telnet doesn't connect, the likely culprits are firewall and/or IPSec.
Firewall? Sounds like firewall to me...

IpEndPoint Problem

The prog in c#:
private void listBox1_Click(object sender, EventArgs e)
{
String data = (String)this.listBox1.SelectedItem;
data = data.TrimEnd(new char[] { '\r', '\n' });
try
{
ip = Dns.GetHostAddresses(data);
}
catch (SocketException ex)
{
MessageBox.Show(ex.ErrorCode.ToString());
}
clientIP = new IPEndPoint(ip[0], 6000);
newSock.Bind(clientIP);
newSock.Listen(100);
resetEvent.Set();
}
In the above code, I obtain the ip-address of the remote host who is shown in the listbox and correspondingly in order to start accepting messages need to create an IPEndPoint(clientIP).
newSock is a variable of type socket initialized as:
newSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
The problem is in the line where I bind the socket newSock to the IPEndPoint clientIP where I am getting an error saying it is an invalid address.
However to cross check I tried to display the ip-address on a message box which it did correctly.
So what exactly is going wrong??
You shouldn't bind a socket to remote host address. It's used to indicate on which inbound IP address you should listen. You should either specify one of your own IP addresses (if you want to listen only on a single IP) or specify IPAddress.Any (0.0.0.0) to listen on all IP addresses you have.
By the way, if you want to connect to a remote address, you shouldn't use Bind at all. You'd just use the Connect method

Categories

Resources