Open TCP port using UDP? - c#

I read something about using UDP to open ports. I can't find the original page I read but I did find this SO answer https://stackoverflow.com/a/1539394
I tried running this code. Perhaps I did something wrong? The idea (in link above) was Alice listens to port 5412, sends a UDP packet to bob from 5412 (the tcp port) to 5411. Bob (who doesn't listen) uses TCP port 5411 (the udp port) to connect to Alice 5412. I use the command line on bob to give alice IP address.
Did I do this wrong? When I run locally using my public IP address (and my network address but not 127.0.0.1) I get the exception A socket operation was attempted to an unreachable network. When I run it on Bob I get a connection timeout exception.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace TcpTest
{
class Program
{
static string localIp = "127.0.0.1";
static string remoteIP = ipaddr;
static void Main(string[] args)
{
//run remotely to connect to you using TCP
if (args.Count() > 0)
{
var t = new TcpClient(new IPEndPoint(IPAddress.Parse(localIp), 5411)); //Force port
t.Connect(args[0], 5412);
return;
}
//Run locally
//Bind TCP port
var l = new TcpListener(5412);
l.Start();
//Send UDP using the listening port to remote address/port
var u = new UdpClient(5412);
u.Connect(remoteIP, 5411);
var buf = new byte[10];
u.Send(buf, buf.Length);
//R
new Thread(SimulateRemote).Start();
//L
var c = l.AcceptTcpClient();
var af=c.Client.RemoteEndPoint;
}
static void SimulateRemote()
{
Thread.Sleep(500);
var t = new TcpClient(new IPEndPoint(IPAddress.Parse(localIp), 5411)); //Force port
t.Connect(myipaddr, 5412);
}
}
}

You can't do that.
TCP ports and UDP ports can't connect to each other. The packets you send from UdpClient.Send() have the Protocol field set to 0x11, the value for UDP, but the TCP stack only recognizes packets with Protocol set to 0x06, the value for TCP. It's part of the most-basic operation of an IP module. See RFC 791 if you want the details.

Related

Why is my Server TcpListener Working with Local Address but not with Public Address? - Exception: The requested address is not valid in its context

I wrote a server and a client program in C# using a TcpListener and a TcpClient and I want them to exchange a string. It works if both PCs are connected to the same network and if I use the local address of the server, but when the PCs are connected to a different network and I use a public address it gives me the following error:
Exception: System.Net.Sockets.SocketException (0x80004005): The requested address is not valid in its context
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at System.Net.Sockets.TcpListener.Start(Int32 backlog)
at System.Net.Sockets.TcpListener.Start()
at Server___Network_Class.Program.Main(String[] args) in D:\Server - Network Class\Program.cs:line 18
This error refers to line 18, which is myList.Start(); but I don't know why it throws this exception. I opened my router port and I set up correctly the Windows Firewall...
Here's the Server and Client code I wrote:
Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Server___Network_Class {
class Program {
static void Main(string[] args) {
try {
IPAddress ipAddress = IPAddress.Parse("146.241.31.193"); //That's the public IP
//Initialize the listener
TcpListener myList = new TcpListener(ipAddress, 51328);
//Start listening the selected port
myList.Start();
Socket socket = myList.AcceptSocket();
ASCIIEncoding asen = new ASCIIEncoding();
socket.Send(asen.GetBytes("Can you read this?"));
socket.Close();
myList.Stop();
}
catch (Exception e) {
Console.WriteLine("Exception: " + e);
}
Console.ReadKey();
}
}
}
Client
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Client___Class_Network {
class Program {
static void Main(string[] args) {
try {
//Inizializzo il client
TcpClient client = new TcpClient();
//Cerco di connettermi al server
client.Connect("146.241.31.193", 51328); //IP and Port i want to connect to
//Stream sul quale inviare e ricevere i dati dal server
NetworkStream stream = client.GetStream();
Byte[] bytesRecived = new Byte[256];
int totBytesRecived = stream.Read(bytesRecived, 0, bytesRecived.Length);
String stringData = System.Text.Encoding.ASCII.GetString(bytesRecived, 0, totBytesRecived);
Console.Write(stringData);
client.Close();
}
catch (Exception e) {
Console.WriteLine("Exception: " + e);
}
Console.ReadKey();
}
}
}
Only the server program throws that exception, the client one seems working file...
Could you please help me out with this problem? I have (almost) searched all over the web but I couldn't find any useful answer.
Thanks in advance!
Is the public IP address really available at your Windows machine or only on the router?
Check if the public address shows up when running ipconfig in the Command line window. My guess is that you need to set up NAT port forwarding in the router and set the application to listen to the IP address your router gave to your Windows machine. Such an IP address typically starts with 10. or 192..
Try binding your server to the address 0.0.0.0. This way, it will listen to all your network cards (WiFi, Ethernet) without the need for any configuration.

C# - Can't receive UDP on second computer

I can send UDP messages from one computer to itself on a certain port but I can't send this messages from one computer to another in the same lan. I am pretty new to C# and I am also new to network programming so the solution is probably easy...
I have tried an example from Microsoft Docs and did only small changes. (names, etc.)
Both codes run as seperate programs.
//RECEIVE
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UDPListener
{
private const int listenPort = 11000;
private static void Listen()
{
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
try
{
while (true)
{
Console.WriteLine("Waiting for broadcast");
byte[] receivebytes = listener.Receive(ref groupEP);
Console.WriteLine(Encoding.ASCII.GetString(receivebytes, 0, receivebytes.Length));
}
}
catch (SocketException e)
{
Console.WriteLine(e);
}
finally
{
listener.Close();
}
}
public static void Main()
{
Listen();
}
}
//SEND
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class Program
{
static void Main(string[] args)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//192.168.2.5 is the IP Address of the receiving computer
IPAddress broadcast = IPAddress.Parse("192.168.2.5");
byte[] bytestosend = Encoding.ASCII.GetBytes("Hi");
IPEndPoint ep = new IPEndPoint(broadcast, 11000);
socket.SendTo(bytestosend, ep);
Console.WriteLine("bytestosend were send");
}
}
The sending program tells me that the message was sent but the receiving program gives no output.
EDIT 1: The Ressource Manager said that on the receiving computer was no network activity while on the sending computer is actually sending something.
EDIT 2: I tried my applications in an other network and it worked fine. I did some research and I found that sometimes routers don't allow udp broadcasts through a subnet (or anything similar...). So I assume it might be my router. (unfortunately I can not access it's settings.) So I think the problem has resolved itself!

C# tcp stream - is it possible to run stream without listener?

I want to write a part of code in which I start sending packages using tcp stream, but without any part that receives it over the internet.
In the meantime I would also like to have another method that can connect to that particular stream at any time and starts receiving bytes from the moment it connects.
I wanted to use multicasting, but I see it's impossible to do it over the Internet
Is there a way to do it? I only found some info so far, that the tcp connection in C# uses point to point way, so my case sounds impossible to implement, because the listener has to be always active to even initialize the streamer, how can I bypass that?
Edit Added an example of a simply "broker" who republishes all messages it receives.
Either use UDP and broadcast your packets to an endpoint that may or maynot be listening at any point in time.
Or use a message queue such as MSMQ, RabbitMQ or 0MQ.
MSMQ may become a problem if the listening service is offline for to long as the messages queue on your dispatch system resulting in a backlog that may fill.
If you would like to create something using UDP here is some code.
Listener (server):
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPLISTENER
{
class Program
{
static void Main(string[] args)
{
var port = 8750;
var listener = new UdpClient(port);
var group = new IPEndPoint(IPAddress.Any, port);
Console.WriteLine("Listening for datagrams on port {0}", port);
while(true)
{
var data = listener.Receive(ref group);
Console.WriteLine("{0}: {1}", group.ToString(), Encoding.Default.GetString(data, 0, data.Length));
}
}
}
}
Broker (Server&Client):
sing System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPCLIENT
{
class Program
{
static void Main(string[] args)
{
int listeningPort = 8749, dispatchPort = 8750;
var listener = new UdpClient(listeningPort);
var group = new IPEndPoint(IPAddress.Any, listeningPort);
// Republish client
var sender = new UdpClient("127.0.0.1", dispatchPort);
Console.WriteLine("Listening for datagrams on port {0}", listeningPort);
while (true)
{
var data = listener.Receive(ref group);
Console.WriteLine("{0}: {1}", group.ToString(), Encoding.Default.GetString(data, 0, data.Length));
sender.Send(data, data.Length);
}
}
}
}
Sender (Client):
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPSENDER
{
class Program
{
static void Main(string[] args)
{
var sender = new UdpClient("127.0.0.1", 8749);
while (true)
{
Console.WriteLine("Message: ");
var data = Encoding.Default.GetBytes(Console.ReadLine());
sender.Send(data, data.Length);
}
}
}
}
Depending what you wish to archive I recommend message queues they give to the most flexibility.
But as you can see UDP works a bit differently to TCP. You don't need a handshake like TCP does, this means if no one is listening to your messages they vanish with no cost to the sender (there is still cost to the network). But if a listener pops up then they start consuming the messages right away. Remember no UDP packet is guaranteed delivery, this is both a blessing and a curse.
If you want messages to be guaranteed you need to implement your own solution, one method is a counter on the datagrams that the listener watches if there is a message missing then it request that message be resent.
You can create a new class derived from Stream, override the Write method, and manage the writing to the tcp clients here. You will be able to write to this stream from your code whether a client is connected or not. When no client is connected, the data will simply be ignored.

How to make more than 1 socket to the same host and port?

I am trying to forward multiple sockets communication to a target socket. So I need to make multiple connection to that target socket, but when I try to connect to it for the second time, I get this:
SocketException: No connection could be made because the target machine actively refused it
I think the problem is with the other end of the socket, i.e port and host and because there is already a connection between port related to my program and target port, to have a second connection I need a second port for my program.
I hope my problem be clear for you guys.
Any Idea how to do it?
This is a test program just to show the problem.
using System;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Text;
class Sample
{
private static ManualResetEvent connectDone = new ManualResetEvent(false);
public static void Main()
{
Socket[] s = new Socket[10];
for (int i = 0; i < s.Length; i++)
{
IPAddress ipAddress;
ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndp = new IPEndPoint(ipAddress, 1100);
// Create a TCP/IP socket.
s[i] = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
connectDone.Reset();
s[i].BeginConnect(localEndp,
new AsyncCallback(ConnectCallback), s[i]);
connectDone.WaitOne();
s[i].Send(Encoding.ASCII.GetBytes(i.ToString() + ": hi.\r\n"));
}
}
private static void ConnectCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
// Signal that the connection has been made.
connectDone.Set();
}
}
I even tried to bind my sockets to different ports, but still second socket gets that exception.
This error message means that there is no open port on that IP. The IP is valid but the remote host replied that it will not accept a connection on this port.
You should be getting this error even for the very first connection.
Find out why the port is not open.
Btw, you use of async connect is counter-productive. You have non of the async benefits and all of the disadvantages. But this is not the point of this question.

Unable to connect from remote machine

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);

Categories