How can a TcpClient be pinged from a server in order to see its response time? I have a TCPServer that I have created with a TCPClientManager that I have also created. This simply adds a new Client with a .NET TcpClient property to aList whenever a client connects. How can I get the address of the TcpClient so that I can ping it using .NET Ping ?
public long PingClient(Client client)
{
long pingTime = 0;
Ping pingSender = new Ping();
// The class Client has a property tcpClient of type TcpClient
IPAddress address = IPAddress.Parse(Client.tcpClient...???);
PingReply reply = pingSender.Send(address);
if (reply.Status == IPStatus.Success)
{
pingTime = reply.RoundtripTime;
}
return pingTime;
}
If I understood your question correctly you want the IPAddress of the connected TcpClient which can be accomplished by accessing the underlaying socket (which is exposed through the Client property) and using it's EndPoint property.
You will have to cast it to an IPEndPoint in order to access it correctly.
In your case just use ((IPEndPoint)client.Client.RemoteEndPoint).Address which will return an IPAddress.
So you would have to change your example from:
IPAddress address = IPAddress.Parse(Client.tcpClient...???);
to:
IPAddress address = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
Related
I'm writing a very simple .NET TCP Server and very simple TCP Client that should both run on the same machine (Window 10 Home PC) and connect each other (for testing purposes only).
In the server I'm waiting for the connection in this way:
public static void StartListening()
{
string hostname = Dns.GetHostName();
IPHostEntry ipHostInfo = Dns.GetHostEntry(hostname);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Properties.Settings.Default.Port);
Socket listener = new Socket(
ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(Properties.Settings.Default.Port);
while (true)
{
allDone.Reset();
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
var frames = Directory.EnumerateFiles(Properties.Settings.Default.FramesPath);
foreach (string filename in frames)
{
Console.Write("Sending frame: {}...", filename);
SendFile(handler, filename);
Thread.Sleep(Properties.Settings.Default.FrameDelay);
}
}
In the client I'm creating a connection in this way:
private void startClient(string host, int port)
{
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port);
ClientTCP = new TcpClient();
ClientTCP.Connect(serverEndPoint);
Reader = new StreamReader(ClientTCP.GetStream());
Listen = true;
listner = Listener();
}
startClient is called in this way.
startClient(txtAddr.Text, (int)int.Parse(txtPort.Text));
When I run the client setting host variable to the current machine name (the same the server retrieve trough Dns.GetHostName() I got this exception:
An invalid ip address was specified.
I tried using 127.0.0.1 and I got:
Connection could not be established. Persistent rejection of the target computer 127.0.0.1:5002
I tried with localhost and I got
An invalid ip address was specified
again. I tried with the IP address assigned to WiFi and I got again
Connection could not be established. Persistent rejection of the target computer 192.168.10.11:5002
I'm sure the computer network works since I'm using it for many other things including connecting to local TCP services and I'm sure both client and server code works since on a different PC I'm able to connect them setting localhost as client host variable value. Why I'm unable to use loopback connections in my code?
Where did I fail?
P.S. I allowed connection to server binary in Windows firewall rules, I also allowed outgoing connection for client binary also.
For anyone willing to inspect the server code here it is:
Server code
You are using the constructor with the "IPEndPoint" parameter. This constructor does not connect to the server automatically and you must call the "Connect" method before using the socket. That is why you are getting the error message "Operation not allowed on unconnected sockets". Also, you have provided a wrong IPEndPoint for client.
Please try this on client:
private void startClient(string host, int port)
{
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port);
ClientTCP = new TcpClient();
ClientTCP.Connect(serverEndPoint);
Reader = new StreamReader(ClientTCP.GetStream());
Listen = true;
listner = Listener();
}
You may need some exception handling here, but it should work now.
UPDATE:
The ipHostInfo.AddressList may have more than one addresses and just one of them is what you wanted. It is not necessarily the first one. I specified this manually and it works:
//string hostname = Dns.GetHostName();
//IPHostEntry ipHostInfo = Dns.GetHostEntry("127.0.0.1");
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5002);
When I try to create a new TcpClient I am getting a SocketException, here is my code:
public void TcpOpenConnection()
{
// The next line is where the exception is occurring.
tcpClient = new TcpClient(ipAddress, port);
connected = true;
}
I have checked to make sure the port is open with netstat -a in cmd, and I even made another function to check if the port is open:
public static bool PortCheck(int port)
{
bool portOpen = false;
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfo = ipGlobalProperties.GetActiveTcpConnections();
foreach (var tcpConn in tcpConnInfo)
{
if (tcpConn.LocalEndPoint.Port == port)
{
portOpen = true;
break;
}
}
return portOpen;
}
which returns true. The exception that I am getting is a SocketException and it is saying the machine I am trying to connect to is actively refusing the connection. What could be the issue here? I have also tried other ports, with no luck.
If you need more info please ask, and I will gladly supply more.
The exception that I am getting is a SocketException and it is saying the machine I am trying to connect to is actively refusing the connection.
This is likely an indication that the target host isn't listening on the port which could be caused by a number of reasons:
The router of the server's network is not correctly port-forwarded
The router's firewall / server's firewall is blocking the connections
The server and the client are not using the same port
The server is misconfigured
The list goes on... but essentially, this error means that the server isn't allowing the connection.
If the port is open and you try to connect to. You get SocketException because there is nothing for get the client connection.
So you need to host a Tcplistner on this port.
static void StartServer()
{
int port = 150;
TcpListener listner = new TcpListener(IPAddress.Any, port);
listner.Start();
// This line waits the client connection.
TcpClient remote_client = listner.AcceptTcpClient();
// do something with remote_client.
}
And you can connect to.
static void StartClient()
{
int port = 150;
IPAddress ip = IPAddress.Parse("127.0.0.1");
TcpClient client = new TcpClient();
client.Connect(ip, port);
// Do something with client.
}
I'm using the the examples provided by Microsoft to learn how to use TCP servers in C#. For TCPListener I use this http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx , and for TCPCLient I use this http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx (the examples are at the bottom of the page).
Until now I've managed to connect and send messages to other PCs connected to the same router. What I want now is to connect it to a PC outside my LAN network. How can I do that ?
I should also mention that this is the way that I use to connect PCs in LAN :
on ther server side:
public string LocalIPAddress()
{
IPHostEntry host;
string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
break;
}
}
return localIP;
}
private void Form1_Load(object sender, EventArgs e)
{
TcpListener server = null;
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
String localAddrString = LocalIPAddress();
Console.WriteLine(localAddrString);
IPAddress localAddr = IPAddress.Parse(localAddrString);
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
}
}
on the client side:
Int32 port = 13000;
String server = "192.168.X.X"; // here I manually introduce the IP provided by the server in the console
TcpClient client = new TcpClient(server, port);
I wish I could use a simple comment to give you this information but I cannot due to me only recently joining SO. You should ensure you have port forwarded (http://portforward.com/ will help you port forward), if you don't know how to you could use this easy-to-use port checker: http://www.yougetsignal.com/tools/open-ports/.
I am currently using this function to send data from the server to the clients
private static void send_message(string ip, string message)
{
byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(message);
int port = 11000;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SendTo(packetData, ep);
}
But this would mean a destination IP/port can only have one client open to receive the data, because having two clients open would mean one client can retrieve data that was meant for another (if I'm correct).. how do I solve this?
Receiving function:
private static Int32 port = 11000;
private static UdpClient udpClient = new UdpClient(port);
public static void receive_threaded()
{
Thread t = new Thread(() =>
{
while (true)
{
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port);
byte[] content = udpClient.Receive(ref remoteIPEndPoint);
if (content.Length > 0)
{
string message = Encoding.UTF8.GetString(content);
parseMessage(message);
}
}
});
t.Start();
}
1) You should implement some kind of protocol so that your server has a "well known" port to accept connections. Use this port to inform your client ANOTHER port where the client must connect. Use a different port for each client.
Your client conects to the server at 11000. Your server assigns a unique port for the client, let's say 11001 for the firts client. Then the server opens a connection at 11001. The client closes connection at 11000 and opens a new connection at 11001 to receive the data.
2) Why UDP?
I don't see why you need to open a new socket at all. You already have each client's address and port, from the first packet they sent you. Just send a packet to that address:port. I absolutely don't get the other suggestion of setting up extra ports either.
I have some kind of problem and I can't check this at home if its working or not.
Here is the code
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net.Security;
class Program
{
private static IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
private static int port = 6000;
private static string data = null;
static void Main(string[] args)
{
Thread thread = new Thread(new ThreadStart(receiveThread));
thread.Start();
Console.ReadKey();
}
public static void receiveThread()
{
while (true)
{
TcpListener tcpListener = new TcpListener(ipAddress, port);
tcpListener.Start();
Console.WriteLine("Waiting for connection...");
TcpClient tcpClient = tcpListener.AcceptTcpClient();
Console.WriteLine("Connected with {0}", tcpClient.Client.RemoteEndPoint);
while (!(tcpClient.Client.Poll(20, SelectMode.SelectRead)))
{
NetworkStream networkStream = tcpClient.GetStream();
StreamReader streamReader = new StreamReader(networkStream);
data = streamReader.ReadLine();
if(data != null)
Console.WriteLine("Received message: {0}", data);
}
Console.WriteLine("Dissconnected...\n");
tcpListener.Stop();
}
}
}
I have a simple program as well to connect to this and then send a string with data. It works fine on localhost but there is a problem when I'm trying to connect with a different coputer.
I even turned off the firewall on my PC and router, as I did on my friend's laptop. Every time I have tried to connect, his computer refused connection. Maybe I'm doing something wrong?
Of course, ipAddress is a local address now since it's only working with that at the moment. Any suggestions what to do?
You need to set it to accept connections from any IP, there is an IPAddress overload function for this:
System.Net.IPAddress.Any
use it instead of 127.0.0.1 and it will fix your problem.
You're listening on 127.0.0.1 which is the loopback address which is a special address that means 'this computer'. This means that you will only accept connections that are made on the same machine as the server is running on.
You need to listen on one (or more) of the server's real ip addresses.
Your problem is that the setting an IP address explicitly when you initialize the TcpListener will only allow it to accept connections from that address. Therefore, putting in the local address of 127.0.0.1 will only accept connections originating from your PC.
The implementation you want to use is as follows:
TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
This will allows connections from any IP address to connect to your program on the specified port.
I think it is your computer (the server) that refuses to connect because 127.0.0.1 is local(-only).
Try this simple overload:
TcpListener tcpListener = new TcpListener(port);