I have few questions (and problems) about the tcp client class.
1. What IP should I give to it constructor, mine or the remote host that I want to connect to? because in MSDN I see that the constructor takes a local ip endpoint and I can't understand it.
2. What may be the reason for such statement:
TcpClient client = new TcpClient(ip.Text, port: portNum);
to stop the code from running without throwing an exception?
1. The IP you should give to the constructor
You should give the IP you want to connect, look about the IPAddress class.
2. The reason of the statement
Why did you type port: portNum ?
Just write like what is writed in the official documentation :
//Creates a TCPClient using host name and port.
TcpClient tcpClientB = new TcpClient ("www.contoso.com", 11000);
System.Net.Sockets.TcpClient has four constructors. The two constructors that seem to be the source of confusion are:
TcpClient(IPEndPoint) - binds it to the specified local endpoint.
TcpClient(String, Int32) - connects to the specified port on the specified host.
Constructor #1 is useful if your computer has more than one NIC (e.g. Ethernet and WiFi) and you want to pick which one to use. If you construct your TcpClient instance this way, then you would explicitly call TcpClient.Connect to connect the remote host and port number.
Constructor #2 creates the TcpClient instance (picking a local endpoint automatically) and immediately connects using the supplied remote host and port.
Related
I am trying to connect to a sensor using network, the sensor's ip is 192.168.2.44 on port 3000;
My Code:
byte[] byteReadStream = null; // holds the data in byte buffer
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("192.168.2.44"), 3000);//listen on all local addresses and 8888 port
TcpListener tcpl = new TcpListener(ipe);
while (true)
{
//infinite loop
tcpl.Start(); // block application until data and connection
TcpClient tcpc = tcpl.AcceptTcpClient();
byteReadStream = new byte[tcpc.Available]; //allocate space
tcpc.GetStream().Read(byteReadStream, 0, tcpc.Available);
Console.WriteLine(Encoding.Default.GetString(byteReadStream) + "\n");
}
But when I run this code, I get this error:
The requested address is not valid in its context
Use IPAddress.Any to listen. This seems to be your goal:
//listen on all local addresses
The listening address you have specified is invalid for some reason. There is no need to specify a numeric address.
The TcpListener listens for connections from TCP network client, on a given port on your local machine. That is, for incoming connections. Your code will be acting as a "server" of sorts.
The requested address is not valid in its context
Simply, it means that the IP address given is not used by any network interface on your machine.
Use IPAddress.Any to listen on any IP address (i.e. network interface).
However, it might be the case that you need to connect to the sensor (on port 3000), not the other way around.
EDIT: The new exception just tells you that you have two applications trying to listen to the same interface/port combination. Do you have two instances running at the same time?
One of the reason for this issue could be the presence of defaultProxy section in the configuration file which would be routing every outgoing call via proxy address mentioned in this setting. Ensure that either there is a proxy server/service listening at the proxy address, or comment this section to stop the routing. In case the application configuration file does not have it, and this error is still there, check for the defaultProxy section in the machine.config file. machine.config should be available in folder C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config. In our case it was the defaultProxy in machine.config.
I have 2 instances of the same application, on different machines, that should talk with each other, where no one is a typical server or client.
Both instances of the application has a TcpListener, local port = 8000.
One application instance (call it "A") creates a TcpClient. Now, this client can't have local port = 8000, or the constructor throws the socket exception "Only one usage of each socket address (protocol/network address/port) is normally permitted".
So, I create this first client with a random local port, and run Connect() to connect with the other application instance "B".
"B" accepts the connection using TcpListener.AcceptTcpClient(), which returns a TcpClient that can be used to communicate with "A". Though, this TcpClient has the same IP and Port as the TcpListener!? How is this possible, when I could not use the same port when I created the TcpClient manually on "A"? I actually really would like them to use the same port as the listener, on both machines...
So, how can I create the TcpClient on "A" with same port as the TcpListener?
I think you might not fully understand the address port client server architecture.
TcpListener is listening to any connection on address and port. After connection established you can use the "Socket" to receive and send messages from the client and server both.
example:
0.0.0.1 is machine A.
0.0.0.2 is machine B.
you can put a TcpListener that is listening on port 8000 on machine A. When the TcpClient on machine B will make try to connect machine A on port 8000 the TcpClient on machine B will get a generated (by the OS) port.
and then you will have a connection
0.0.0.1:8000 -> 0.0.0.2:3587(Generated port) - so you dont need to worry for the client listening port.
A TCP Connection has always a server and a client side. The server is listening (waiting) for a connection and the client connects to the server.
When the server gets the connection request, AcceptTcpClient gives you the socket of the server side to communicate with the client. A TCP Connection is always defined with the IP Addresses and Ports of the two sides: serverip:serverport and clientip:clientport.
If you want a really symmetrically System, both instances would have a server and a client that connects to the other server. All data that would then always be sent from client to server over the connection that was established by the client.
For Example:
ClientA connects to ServerB -> ConnectionAB
ClientB connects to ServerA -> ConnectionBA
ApplicationA sends data to ApplicationB over ConnectionAB
ApplicationB sends data to ApplicationA over ConnectionBA
If your goal is to use 2 TCP endpoints to talk to each other, without one of them being an
explicit server always, you probably should run a listener (on port 8000, in your case)
on both machines. Next, let each machine try randomly for the connection -- let each
machine pick a random time (between 0 and T) and then wake up. Whichever machine
wakes up first, will call connect() and establish the connection.
As #nivpenso pointed, the end point doing the connect need not explicitly bind to
a port. The connect() step explicitly assigns a temporary random port to that
end point.
So, if hostA initiates the connection, here are all the endpoints you would see
(you can use netstat to see these connections)
HostA:
-- listener: 8000
-- connection to hostB:port8000, localport:xyz
HostB:
-- listener: 8000
-- connection to hostA:port:xyz, localport:8000
On the other hand, if hostB initiates the connection, here are all the endpoints you
would see:
HostA:
-- listener: 8000
-- connection to hostB:port:xyz', localport:8000
HostB:
-- listener: 8000
-- connection to hostA:port8000, localport:xyz'
In the Internet, BGP uses a similar method to connection 2 TCP peers.
Consider the following:
IPEndPoint ep = new IPEndPoint(ip, 0);
TcpClient tcpClient = new TcpClient (ep);
tcpClient.Connect(ep);
Why must I tell the tcpClient to first bind to ep and the connect to ep. I seems strange compared to just Connect() to the already bound end point.
The constructor that accepts an IPEndpoint is meant for binding a local endpoint address. Connect is meant to be passed a remote endpoint address. One of these two things is in contradiction with the other.
constructor:
Initializes a new instance of the TcpClient class and binds it to the specified local endpoint.
Connect:
Connects the client to a remote TCP host using the specified remote network endpoint.
But since we don't know whether ep is a local or remote endpoint, I can't tell you which one is wrong. I would guess at a local endpoint since you've specified 0, in which case you need to identify a different endpoint for your Connect call - what are you trying to connect to?
Not sure if I'm missing something here, but there is a default constructor.
http://msdn.microsoft.com/en-us/library/aa329755(v=vs.71).aspx
I am doing projects in sockets.usually the server listens in a particular port,and the client has to connect to the port then the send and receives will happen.but we don't specify any port number in the client side,but i am in a situation to use a port in a client side, through this port only the messages will delivered to the server.how to do this?
In my client side they are restricting the ports ,so if want use to a valid free port i have to set it in the client program,instead of OS Choosing it.This is my problem.
Bind the client socket to local address (ip and port number) before connecting to server. Be ready to handle errors e.g. when the port is not available (choose next port, retry).
I guess you're using the System.Net.Sockets namespace?
If so, classes like NetworkStream take the Socket as a constructor parameter:
http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.aspx
Similarly, the TcpClient takes Port and Server as constructor arguments, Port is the same as socket in this context:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx
Finally. you can control the number of this socket in a few ways:
Command Line Parameter
Setting in an Application.Config file
Read it from the Registry
There are a few methods for this type of thing.
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?