public Server([Optional, DefaultParameterValue(0x6c1)] int port, [Optional, DefaultParameterValue("127.0.0.1")] string ip)
{
this.IP = IPAddress.Parse(ip);
this.Port = port;
this.listenerConnection = new TcpListener(this.IP, this.Port);
this.listenerConnection.Start();
this.listenerThread = new Thread(new ThreadStart(this.listen));
this.listenerThread.Start();
}
is the code I have, it runs fine but when I debug it, I get the message:
Specified argument was out of the range of valid values. Parameter name: port
Can anyone help?
Well, then port is out of the range of valid values, which is between IPEndPoint.MinPort and IPEndPoint.MaxPort.
Have you tried using the IPAddress of your machine? You can use the following code to obtain the IPAddress of the machine you are running the application on:
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
IPAddress localIpAddress = null;
forach(IPAddress address in host.AddressList)
{
if(address.AddressFamily == AddressFamily.InterNetwork)
{
localIpAddress = address;
}
}
TcpListener listener = new TcpListener(localIpAddress, port);
listener.Start();
Additionally, you may want to consider using a default port > 5000. As there are many ports between 0 and 5000 that are reserved or already use by services.
Related
I want to connect android with windows so that i can send my custom data.
so far i have only seen localhost examples.
but i want to connect my android which is on Sim-internet with windows connected through Ethernet.
this is android's code so far(client)
socket = Socket(address, port)
outputStream = socket.getOutputStream()
outputStream.write(data)
and this is C# windows(server)
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("localhost");//localServer
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint ipEndPoint = new(ipAddress, 10090);
Console.WriteLine("initiating " + ipEndPoint.Port + ", " + ipAddress.ToString());
using Socket listener = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
var handler = await listener.AcceptAsync();
while (true)
{
// Receive message.
var buffer = new byte[1_024];
var received = await handler.ReceiveAsync(buffer, SocketFlags.None);
var response = Encoding.UTF8.GetString(buffer, 0, received);
var eom = "<|EOM|>";
if (response.IndexOf(eom) > -1 /* is end of message */)
{
Console.WriteLine(
$"Socket server received message: \"{response.Replace(eom, "")}\"");
break;
}
}
as you can see it is localhost which can only be accessed by localNetworked devices
but i want to connect it over internet from different networked devices
How can i implement that .?
Your socket should bind to all addresses, not the local (new IPEndPoint(IPAddress.Any, ...)).
Your server is most likely behind a firewall/NAT so you need to setup port forwarding so your server can be accessed from the internet.
If the servers public IP address is static then you can use that. Otherwise you have to purchase a domain and configure a DNS server or use a free dynamic DNS service like No-IP or FreeDNS...
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);
I don't know if I'm just not searching using the right keywords, I want to be able to find the IP address of my local computer that was assigned by my router.
I was using:
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach(IPAddress ip in host.AddressList)
{
if(ip.addressfamily.tostring() == "InterNetwork")
{
return ip;
}
}
The problem is I have multiple InterNetwork ip addresses because I use virtual services, so I need to be able to identify which one was assigned by my router.
How about loopback?
if (IPAddress.IsLoopback(ip)) return ip; //localhost
Or try pinging the local machine
Ping pingSender = new Ping ();
IPAddress address = IPAddress.Loopback;
PingReply reply = pingSender.Send (address);
if (reply.Status == IPStatus.Success){..}
also this might help you
Showing The External IP-Address In C#
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/.
To test my server/client application, where each client is known by its IP address, I created several network adapters (see How to Create a Virtual Network Adapter in .NET?). Both 192.168.0.10 and 11 now correspond to local ethernet adaptors (10 being the "real" one, 11 being a loopback adapter).
The client can Connect itself to the server as long as it doesn't Bind its socket to a specific address. But if it does, the server doesn't notice anything and a timeout occurs in the client (I want to use Bind as for security reasons the server automatically detects which client is connecting itself by looking at the IP address of the remote end point of the new connection: the server will drop the connection at once if it doesn't know the IP address - previously I was using several virtual machines, but it uses a lot more RAM and is less practical to use).
Here's the code in my server, listening eg on 192.168.0.10:1234
IPEndPoint myEP = new IPEndPoint(myAddress, myPort);
Socket listeningSocket = new Socket(myAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listeningSocket.Bind(myEP);
listeningSocket.Listen(50);
Socket acceptedSocket = listeningSocket.Accept();
Here's the code in my client, binding eg to 192.168.0.11 (any port) and connecting to 192.168.0.10:1234
Socket socket = new Socket(svrAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(myAddress, 0)); // Bind to local address using automatic port
socket.Connect(new IPEndPoint(svrAddress, svrPort)); // Works fine without Bind, timeout with Bind
I've tried the same using the corresponding IPv6 addresses but I get the exact same result.
If I Bind the client on the same address (using a different port than the server), it works fine.
Any idea what I'm doing wrong?
EDIT Here is my test projects (it might be useful to someone)
Server part:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Server
{
class Program
{
static void Main(string[] args)
{
IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
string line = string.Empty;
while (line != "q")
{
// Gets the IP address to listen on.
Console.WriteLine("IP to listen on:");
int count = 0;
foreach (IPAddress ip in ips)
Console.WriteLine("{0}: {1}", ++count, ip.ToString());
string numString = Console.ReadLine();
int pos = Convert.ToInt32(numString) - 1;
IPAddress myAddress = ips[pos]; // Removing or not the scope ID doesn't change anything as "localEndPoint" below will contain it no matter what
// Binds and starts listening.
IPEndPoint myEP = new IPEndPoint(myAddress, 12345);
Socket listeningSocket = new Socket(myAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listeningSocket.Bind(myEP);
listeningSocket.Listen(50);
IPEndPoint localEndPoint = (IPEndPoint)listeningSocket.LocalEndPoint;
Console.WriteLine("Listening on {0}:{1}", localEndPoint.Address, localEndPoint.Port);
Task.Factory.StartNew(() =>
{
try
{
// Accepts new connections and sends some dummy byte array, then closes the socket.
Socket acceptedSocket = listeningSocket.Accept();
IPEndPoint remoteEndPoint = (IPEndPoint)acceptedSocket.RemoteEndPoint;
Console.WriteLine("Accepted connection from {0}:{1}.", remoteEndPoint.Address, remoteEndPoint.Port);
acceptedSocket.Send(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
acceptedSocket.Close(5000);
Console.WriteLine("-= FINISHED =- Type q to quit, anything else to continue");
}
catch (Exception ex)
{ }
});
line = Console.ReadLine();
// Closes the listening socket.
listeningSocket.Close();
}
}
}
}
Client part
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
string line = string.Empty;
while (line != "q")
{
// Gets the IP address to connect to (removes the "scope ID" if it's an IPv6).
Console.WriteLine("IP to connect to:");
int count = 0;
foreach (IPAddress ip in ips)
Console.WriteLine("{0}: {1}", ++count, ip.ToString());
string numString = Console.ReadLine();
int pos = Convert.ToInt32(numString) - 1;
IPAddress svrAddress = ips[pos].AddressFamily == AddressFamily.InterNetworkV6
? new IPAddress(ips[pos].GetAddressBytes())
: ips[pos];
Console.WriteLine("Connecting to " + svrAddress);
// Gets the IP address to bind on (can chose "none" - also removes the "scope ID" if it's an IPv6).
Console.WriteLine("IP to bind to:");
Console.WriteLine("0: none");
count = 0;
IPAddress[] filteredIps = ips.Where(i => i.AddressFamily == svrAddress.AddressFamily).ToArray();
foreach (IPAddress ip in filteredIps)
Console.WriteLine("{0}: {1}", ++count, ip.ToString());
numString = Console.ReadLine();
pos = Convert.ToInt32(numString) - 1;
IPEndPoint localEndPoint = (pos == -1)
? null
: new IPEndPoint(
filteredIps[pos].AddressFamily == AddressFamily.InterNetworkV6
? new IPAddress(filteredIps[pos].GetAddressBytes())
: filteredIps[pos]
, 0);
Console.WriteLine("Binding to " + (localEndPoint == null ? "none" : localEndPoint.Address.ToString()));
// Binds to an address if we chose to.
Socket socket = new Socket(svrAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (localEndPoint != null)
socket.Bind(localEndPoint);
Task.Factory.StartNew(() =>
{
try
{
// Connects to the server and receives the dummy byte array, then closes the socket.
socket.Connect(new IPEndPoint(svrAddress, 12345));
IPEndPoint remoteEndPoint = (IPEndPoint)socket.RemoteEndPoint;
Console.WriteLine("Connected to {0}:{1}", remoteEndPoint.Address, remoteEndPoint.Port);
byte[] buffer = new byte[10];
Console.WriteLine((socket.Receive(buffer) == buffer.Length) ? "Received message" : "Incorrect message");
socket.Close();
}
catch (Exception ex)
{
// An exception occured: should be a SocketException due to a timeout if we chose to bind to an address.
Console.WriteLine("ERROR: " + ex.ToString());
}
Console.WriteLine("-= FINISHED =- Type q to quit, anything else to continue");
});
line = Console.ReadLine();
}
}
}
}
Actually it was a configuration issue with my network adapters and it has to do with "Weak and Strong Host model".
From what I've read ( Using a specific network interface for a socket in windows ) binding on Windows previous to Vista would only work for incoming traffic, and it wouldn't do anything for outgoing traffic.
Starting with Vista it's possible but by default it won't work: you need to allow the "weak host model" using
netsh interface ipv4 set interface "loopback" weakhostreceive=enabled
netsh interface ipv4 set interface "loopback" weakhostsend=enabled
See https://web.archive.org/web/20150402200610/http://blog.loadbalancer.org/direct-server-return-on-windows-2008-using-loopback-adpter/ for more info.
EDIT
Actually, instead of creating several loopback adapters and changing their host model, it's a lot better and easier to just create one loopback adapter, give it several IP addresses on a different network than your real IP, and then only use those IPs for your test. That way there's no routing issue, and you're sure everything stays local (as there's no routing between the real and loopback adapter).
Use below code in the server for binding the connection on all the interface on the same port.
// Binds and starts listening.
IPEndPoint myEP = new IPEndPoint(IPAddress.Any, 12345);