I'm trying to make a basic client/server program, but when I start the TcpListener it gives me SocketException:The requested address is not valid in its context.
I actually have a method that returns my public IP, and it matches ipconfig results, so the IP address string below can't be the problem. Of course, the IP shown below isn't my real IP for security reasons. I opened the port below for general use.
Anyway, Not valid in context is vague, so I'm not sure what that means.
Here's my code (for the TcpListener):
ServerIn = new TcpListener(IpAddress.Parse("100.100.100.100"), 8000);
ServerIn.Start();
Thanks in advance.
The TcpListener can only be bound to a local IP Address of the computer that runs it. So the IP you're specifying isn't an IP of the local machine. Your public IP isn't the same IP as your local machine, especially if you're using some kind of NAT.
If I recall correctly, it's common to just do IPAddress.Any as your IP to initialise the listener.
As written in MSDN about TcpListener
IPAddress- An IPAddress that represents the
local IP address.
So it need to be a local IP address.
Related
I have a very simple http server:
TcpListener server = new TcpListener(System.Net.IPAddress.Any, 80);
server.Start();
var client = server.AcceptTcpClient();
var ip = client.Client.RemoteEndPoint;
// ip address in here is: 166.72.162.85
// etc. read request and write response....
I am making that request with my phone that is connected to AT&T 3G network. And my server detects the ip address 166.72.162.85
Now here is my question. I am asking this question primary to learn. Why is it that google captures a different IP address? How can I capture 2600:387:9:3::c7 with my TcpListener?
It looks like you're on a dual stacked network - you have both IPv4 and IPv6 connectivity, which a bit like being connected to two separate "Internets" at the same time.
Your server is probably accessible from only one of these "Internets" - the IPv4 Internet. Google is accessible from both. We can easily check that by resolving www.google.com to an IP address. Here's the result on my machine:
Note the first result - 2a00:1450:4001:821::2004. It's an IPv6 address, and that's the first address your operating system will try to connect to when accessing www.google.com because modern operating systems prefer IPv6 over IPv4. So your connection to Google goes over IPv6, which will see you coming from your IPv6 address (2600:387:9:3::c7).
When connecting to your IPv4-only sever, the connection is made over IPv4 - from your IPv4 address, which is 166.72.162.85 to the server's IPv4 address.
To reach your server using IPv6, you'd need to make it accessible via IPv6:
The machine on which you run your server must have a public IPv6 address
The client has to access the machine either directly by its IPv6 address, or a domain name which has a AAAA record, which is a DNS record for IPv6 addresses
On top of that, you need to make sure that your server software binds to the IPv6 address of the machine. Your code binds to System.Net.IPAddress.Any, which is equivalent to 0.0.0.0, meaning "any IPv4 address". Instead, you'd need to bind to IPAddress.IPv6Any, which is equivalent to 0:0:0:0:0:0:0:0 (or ::), meaning "any IPv6 address".
BTW, you can try getting your IP from the IPv4-only Google at https://ipv4.google.com/. It should return the same 166.72.162.85 that you're seeing in your server.
Google is showing an IPv6 address, your code is showing IPv4.
Note you can also see different IP on the receiving end depending on the route the traffic has taken to get there, like if there were a proxy involved you would see the IP of the proxy and not the actual IP of the source.
Writing a chat program (as so many do) and i have found that i would like to be able to get the clients to connect to the server automatically.
However, the IP address of the server would not be permanent, so i cannot just hard-core it into the program
In TCP, I'm looking for some sort of broadcast feature, that allows the client to know where the server is
Any ideas?
EDIT: should have said, this will be a LAN program only - no outside connections
If you are talking about a chat in a LAN and you can't or don't want to use DNS for some reason, you could implement, or find an implementation of, the discovery protocol used by UPnP. The SSDP is based on a UDP broadcast. It is, afaik, not possible to multicast via TCP, because TCP needs a session.
If you want to use the chat server over the internet you have no choice but to use DNS. Look for a dynamic dns provider (I use selfhost.bz). In C# you can then resolve the hostname to an IP address as described in the other answers. If you have a hostname to connect to it will probably be enough to pass that to the socket, though:
socket.Connect("myhostname.selfhost.bz", ...
Edit: Since you say you're in a LAN, a few more details on SSDP. The protocol does way more, than you actually need. If you're thinking of implementing it yourself, don't stick to it exactly. Just make your clients send a broadcast on a specified port. The server permanently listens on that port, answering with a predefined message, once it receives a message. When the client receives that answer, it will know that the sender is a valid server.
Use DNS. Resolve the hostname in your app and connect to the IP it resolves to. You'll need dynamic DNS since you say the IP isn't permanent.
Use the below process to find server IP address
public string GetIPAddress()
{
string strHostName = System.Net.Dns.GetHostName();
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
return ipAddress.ToString();
}
You can also use
Request.ServerVariables["LOCAL_ADDR"];
I had an idea: just get the server to write the IP address/port/whatever to a textfile somewhere on the (public) network, and the clients can read the text file
Obviously, if the text file is not there or empty, no server is running...
Is this such a bad idea?
I have two standalone exe's Parent.exe and Child.exe.
Parent.exe opens Child.exe and some operation are performed in child.exe by user then
child.exe sends back some processed data to Parent.exe. Both exe's stays on same machine
The communication between Child.Exe and Parent.Exe is being done through TCP IP (Socket Programming). For this we need to calculate the Local IP Address, we used to calculate it in the following way :-
string hostname = Dns.GetHostName();
IPHostEntry ipEntry = Dns.GetHostEntry(hostname);
IPAddress[] addr = ipEntry.AddressList;
string FinalIpAddrs = addr[0]
Everything worked fine at XP but with Windows 7 we are facing problem. The below line return Mac Address what is the right way to do it, so that it works on XP and Win7 both?
string FinalIpAddrs = addr[0]
Oh, those wh program and do not know.
You do NOT need to know an IP Address, use 127.0.0.1, which is a local loopback address. SImple like that - it is there for exactly that reason.
Consider being efficient. If that is all same machine, the usage of TCP is bad. Use named pipes, which are a windows integrated commmunciation mechanism that CAN work cross machine, but on the same machine it uses shared memory which is a LOT more efficient than TCP.
Why not just use IPAddress.Loopback (or IPv6Loopback)?
The loopback addresses are designed for communications entirely on the same host.
I'm also guessing that where you say:
The below line return Mac Address
What you actually mean is that it's returning an IPv6 address. There's no way that that code should be able to return a MAC Address.
Is there a specific requirement NOT to use 127.0.0.1? If no, then I'd just use it without any calculations.
I have a program in C# that I want to get a news feed from a server I setup in my basement. I also want to setup this program so it can work locally. To do this I THINK I need to compare the resolved ip of my dyndns.biz hostname to my router's public ip (I have dynamic ip and a client on my server updating the ip of the hostname) and thus determine if the hostname needs to be used or the local ip of the server (192.168.0.100) or the hostname. I already have code to connect to the ftp server assuming I can get the right usage of the hostname versus the localized IP.
Edit: Anyways, in summary because I realized this might not look like a question, how can I determine a) the resolved IP of the hostname and b) the public IP of my router in a C# app
You're overcomplicating this.
Just open your hosts file (found in C:\Windows\System32\drivers\etc) and add your dyndns hostname routing it to loopback. That way you don't have to add any workaround code to your final application to prevent it from even asking your DNS or router:
127.0.0.1 yourhostname.dyndns.biz
To obtain the IP address of a hostname, use the following code:
IPAddress[] addresses = System.Net.Dns.GetHostAddresses("www.cnn.com");
To obtain your public IP address of your router or local network, you need to talk to an outside system that can tell you that part, and unfortunately I don't know if there is any such system that is free to use as well as easy to use from a program.
I am running a client/server application. I use a textbox to let the user type in the IP address and port. I try to connect to the server, using 127.0.0.1 and there is no problem. After that I tried using 192.168.2.102 (NAT ip address of this computer), and it fails. Any idea why?
the code I am using is: (this the the part that connects)
connect(string IPaddress, int port)
{
TcpCLient connection = new TcpClient();
connection.Connect(IPaddress, port);
}
I checked with debug, it DOES use the right IPaddress and port.
Firewall should allow it to connect. It's weird.
EDIT:
I think I know the problem. At the server side, I use
_listener = new TcpListener(IPAddress.Loopback, 8001);
And I think that's the reason why it only accepts connections from 127.0.0.1. But then, what should I use instead? I just want any connection from any IP with this port.
If you are specifying IPAddress.Loopback, then only connections to 127.0.0.1 will work. Replace it with IPAddress.Any to tell your server to listen on all interfaces.
First of all, the only circumstance I've ever seen return Connection was not possible because the destination computer actively rejected it is when there is actually nothing listening for connections at the specified address and port... or there is a firewall.
You may want to verify with a tracert that 192.168.2.102 actually points where you think it does. Another option is to use telnet from the command line to connect to the address and port if you really suspect there is a problem in your code (although I cannot see that apply here).
Addendum:
Is there any other application that can successfully make a connection to that specific IP address on that same machine?