UDP Port Hole Punching C# - udp

i am trying to make two clients behind NAT communicates each other using a server with port forward working, my scenario:
Server start listering on port 45000 for Client_A connection;
Server Start listering on port 45001 for Client_B connection;
Client_A connect to server on port 45000 and send hello message;
Client_B connect to server on port 45001 and send hello message;
Server Receive hello message from Client_B and send message with Client_B external port (ex 56000) to Client_B;
Client_B receive external port and start listering on port 56000;
Server Receive hello message from Client_A and send message with Client_B IP and port to Client_A;
Client_A receive IP and Port of Client_B;
Client_A connect to Client_B and send hello message
The problem:
Client_B does not receive message from Client_A;
Here is the code:
Server:
static int server_A_Port = 45000;
static int server_B_Port = 45001;
static UdpClient server_A;
static UdpClient server_B;
static bool client_B_Connected = false;
static string client_A_Ip = "";
static string client_B_Ip = "";
static int client_A_Port = 0;
static int client_B_Port = 0;
static Thread Server_A_Thread = new Thread(Start_Server_A);
static Thread Server_B_Thread = new Thread(Start_Server_B);
static void Main(string[] args)
{
Server_A_Thread.Start();
Server_B_Thread.Start();
}
static void Start_Server_A()
{
Console.WriteLine("Starting Server_A on port: " + server_A_Port);
server_A = new UdpClient();
IPEndPoint client_A_IpEp = new IPEndPoint(IPAddress.Any, server_A_Port);
server_A.Client.Bind(client_A_IpEp);
Console.WriteLine("Server Started. Waiting Client_A Message");
string c_a = "";
while (string.IsNullOrEmpty(c_a))
{
try
{
c_a = ReceiveMessageFromClient(server_A, ref client_A_IpEp);
Console.WriteLine("Message received from Client_A: " + c_a);
client_A_Ip = ((IPEndPoint)client_A_IpEp).Address.ToString();
client_A_Port = ((IPEndPoint)client_A_IpEp).Port;
server_A.Connect(client_A_IpEp);
}
catch(Exception err)
{
Thread.Sleep(1000);
}
}
Console.WriteLine("Waiting Client_B connection");
bool sended = false;
while (!sended)
{
if(client_B_Connected)
{
Console.WriteLine("Client_B connected, sending Client_B IP and Port to Client_A");
SendMessageToClient(server_A, client_B_Ip + ":" + client_B_Port);
sended = true;
Console.WriteLine("Message Sended to Client_A");
break;
}
Thread.Sleep(1000);
}
Console.ReadLine();
}
static void Start_Server_B()
{
Console.WriteLine("Starting Server_B on port: " + server_B_Port);
server_B = new UdpClient();
IPEndPoint client_B_IpEp = new IPEndPoint(IPAddress.Any, server_B_Port);
server_B.Client.Bind(client_B_IpEp);
Console.WriteLine("Server Started. Waiting Client_B Message");
string c_b = "";
while (string.IsNullOrEmpty(c_b))
{
try
{
c_b = ReceiveMessageFromClient(server_B, ref client_B_IpEp);
Console.WriteLine("Message received from Client_B: " + c_b);
client_B_Ip = ((IPEndPoint)client_B_IpEp).Address.ToString();
client_B_Port = ((IPEndPoint)client_B_IpEp).Port;
server_B.Connect(client_B_IpEp);
client_B_Connected = true;
}
catch (Exception err)
{
Thread.Sleep(1000);
}
}
Console.WriteLine("Sending external Port to Client_B start listering");
SendMessageToClient(server_B,client_B_Port + "");
}
static void SendMessageToClient(UdpClient client, string message)
{
byte[] data = Encoding.GetEncoding(28591).GetBytes(message);
client.Send(data, data.Length);
}
static string ReceiveMessageFromClient(UdpClient client, ref IPEndPoint ep)
{
byte[] data = client.Receive(ref ep);
string receivedString = Encoding.GetEncoding(28591).GetString(data);
return receivedString;
}
Client_A
static string serverIp = "X.X.X.X";
static int serverPort = 45000;
static string otherClientIp = "0.0.0.0";
static int otherClientPort = 0;
static UdpClient client = new UdpClient();
static void Main(string[] args)
{
Console.WriteLine("Connecting to server...");
client.Connect(serverIp, serverPort);
Console.WriteLine("Connected. Sending request message...");
SendMessageToServer();
Console.WriteLine("Sended. Waiting response...");
string s = "";
while (string.IsNullOrEmpty(s))
{
try
{
s = ReceiveMessageFromServer();
Console.WriteLine("Response received from server.");
}
catch (Exception err)
{
Thread.Sleep(1000);
}
}
string[] otherClientInfo = s.Split(':');
otherClientIp = otherClientInfo[0];
otherClientPort = int.Parse(otherClientInfo[1]);
Console.WriteLine("Other Client info: " + otherClientIp + ":" + otherClientPort);
Thread.Sleep(2000);
Console.WriteLine("Connecting to Client_B...");
client.Connect(otherClientIp, otherClientPort);
Console.WriteLine("Connected. Sending hello hessage...");
SendMessageToClient();
Console.WriteLine("Sended. Waiting response...");
string c = "";
while (string.IsNullOrEmpty(c))
{
try
{
IPEndPoint ep = (IPEndPoint)client.Client.RemoteEndPoint;
c = ReceiveMessageFromClient(client,ref ep);
Console.WriteLine("Response received from Client_B.");
Console.WriteLine("Response: " + c);
Console.ReadLine();
}
catch (Exception err)
{
Thread.Sleep(1000);
}
}
}
static void SendMessageToServer()
{
byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT TO SERVER");
client.Send(data, data.Length);
}
static void SendMessageToClient()
{
byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT_A TO CLIENT_B");
client.Send(data, data.Length);
}
static string ReceiveMessageFromServer()
{
IPEndPoint serverIpEp = new IPEndPoint(IPAddress.Parse(serverIp), serverPort);
byte[] data = client.Receive(ref serverIpEp);
string receivedString = Encoding.GetEncoding(28591).GetString(data);
return receivedString;
}
static string ReceiveMessageFromClient(UdpClient server, ref IPEndPoint ep)
{
byte[] data = server.Receive(ref ep);
string receivedString = Encoding.GetEncoding(28591).GetString(data);
return receivedString;
}
Client_B
static string serverIp = "X.X.X.X";
static int serverPort = 45001;
static UdpClient client = new UdpClient();
static void Main(string[] args)
{
Console.WriteLine("Connecting to server...");
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Connect(serverIp, serverPort);
Console.WriteLine("Connected. Sending request message...");
SendMessageToServer();
Console.WriteLine("Sended. Waiting response...");
string s = "";
while (string.IsNullOrEmpty(s))
{
try
{
s = ReceiveMessageFromServer();
Console.WriteLine("Response received from server.");
}
catch (Exception err)
{
Thread.Sleep(1000);
}
}
Console.WriteLine("My External Port: " + s);
//IPEndPoint ep = new IPEndPoint(IPAddress.Any, ((IPEndPoint)client.Client.LocalEndPoint).Port);
IPEndPoint ep = new IPEndPoint(IPAddress.Any, int.Parse(s));
Console.WriteLine("Start Binding on Extenal Port: " + ep.Port);
UdpClient server = new UdpClient();
server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
server.Client.Bind(ep);
Console.WriteLine("Started. Waiting hello message...");
string c = "";
while (string.IsNullOrEmpty(c))
{
try
{
c = ReceiveMessageFromClient(server, ref ep);
Console.WriteLine("Response received from Client_A.");
Console.WriteLine("Response: " + c);
client.Connect(ep);
Console.ReadLine();
}
catch (Exception err)
{
}
}
Console.WriteLine("Sending message to Client_A...");
SendMessageToClient();
Console.WriteLine("Sended.");
Console.ReadLine();
var myRule = FirewallManager.Instance.Rules.SingleOrDefault(r => r.Name == "TEST_RULE");
FirewallManager.Instance.Rules.Remove(myRule);
}
static void SendMessageToServer()
{
byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT TO SERVER");
client.Send(data, data.Length);
}
static void SendMessageToClient()
{
byte[] data = Encoding.GetEncoding(28591).GetBytes("FROM CLIENT_B TO CLIENT_A");
client.Send(data, data.Length);
}
static string ReceiveMessageFromServer()
{
IPEndPoint serverIpEp = new IPEndPoint(IPAddress.Parse(serverIp), serverPort);
byte[] data = client.Receive(ref serverIpEp);
string receivedString = Encoding.GetEncoding(28591).GetString(data);
return receivedString;
}
static string ReceiveMessageFromClient(UdpClient server, ref IPEndPoint ep)
{
byte[] data = server.Receive(ref ep);
string receivedString = Encoding.GetEncoding(28591).GetString(data);
return receivedString;
}
I have no idea what's wrong and how to make it work, I've researched a lot and haven't found the solution.
Sorry for bad english

Related

How to get Messages by the consumer according to priority of the messages set by the publishers RabbitMQ

I have publish messages with some priority set for a single consumer(i.e single consumer that may receive messages according to message priority).
What i want is to get that messages and print them according to the message priority on the consumer side. Hey guys Help me out in this !
public class Send extends Thread {
int priority;
String name = "";
String app_type = "";
private static final String EXCHANGE_NAME = "topic_exchange";
public void run()
{
ConnectionFactory connFac = new ConnectionFactory();
connFac.setHost("localhost");
try {
Connection conn = connFac.newConnection();
Channel channel = conn.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME,
BuiltinExchangeType.TOPIC);
for(int j=1; j<=200; j++)
{
randomWait();
int random = (int)(Math.random() * 10 + 1);
String routingKey = j+"."+"update"+"."+app_type;
String msg = name;
channel.basicPublish(EXCHANGE_NAME, routingKey, new
AMQP.BasicProperties.Builder()
.contentType("text/plain")
.deliveryMode(2)
.priority(priority)
.build(),
msg.getBytes("UTF-8"));
System.out.println("Sent " + routingKey + " : " + msg +
" "+" Priority : "+priority);
}
channel.close();
conn.close();
} catch (IOException ex) {
Logger.getLogger(Send.class.getName()).log(Level.SEVERE, null,
ex);
System.out.println("Exception1 :--"+ex);
} catch (TimeoutException ex) {
Logger.getLogger(Send.class.getName()).log(Level.SEVERE, null,
ex);
System.out.println("Exception 2:--"+ex);
}
}
void randomWait()
{
try {
Thread.currentThread().sleep((long)(200*Math.random()));
} catch (InterruptedException x) {
System.out.println("Interrupted!");
}
}
public static void main(String[] args) {
// TODO code application logic here
Send test1 = new Send();
test1.name = "Hello ANDROID";
test1.app_type = "ANDROID";
test1.priority = 10;
Send test2 = new Send();
test2.name = "Hello ANDROID";
test2.app_type = "ANDROID";
test2.priority = 5;
test1.start();
test2.start();
}
}
In the above code I have use thread to pass the priority and message value and started the both the thread at the same time to publish messages with different priorities. I have set the priority value in the AMQ Builder.
The queue has to be configured to support priority.

Client and Server UDP transport layer

I need to send a message saying "Hi" from client to a server, the server will reply back to the client adding to the received message "Received", once the client receives this new message it will send this to another server and that server will add another message to the received message saying "Replied". So in the end the client will receive the message "Hi Received Replied".
Client code:
public class UDPClient{
public static void main(String args[]) {
// args[0] = message to be sent to the server;
// args[1] = IP address of the server
DatagramSocket aSocket=null;
try {
aSocket=new DatagramSocket();
byte [] m = args[0].getBytes();
InetAddress aHost = InetAddress.getByName(args[1]);
int serverPort = 6789;
DatagramPacket request = new DatagramPacket(m,args[0].length(), aHost, serverPort);
aSocket.send(request);
byte[] buffer = new byte[1000];
DatagramPacket reply = new DatagramPacket(buffer,buffer.length);
aSocket.receive(reply);
System.out.println("Reply: " + new String(reply.getData(), 0, reply.getLength()));
}catch (SocketException e){System.out.println("Socket: " + e.getMessage());
}catch (IOException e){System.out.println("IO: " + e.getMessage());
}finally {
if(aSocket != null) aSocket.close();
}
}
}
Server Code:
public class UDPServer{
public static void main(String args[]) {
DatagramSocket aSocket = null;
try{
aSocket = new DatagramSocket(6789);
byte[] buffer = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buffer,buffer.length);
aSocket.receive(request);
System.out.println("Server is ready and waiting for requests ... ");
DatagramPacket reply = new DatagramPacket(request.getData(), request.getLength(),request.getAddress(), request.getPort());
}
}catch (SocketException e){System.out.println("Socket: " + e.getMessage());
}catch (IOException e) {System.out.println("IO: " + e.getMessage());
}finally {
if(aSocket != null) aSocket.close();
}
}
}

akka fails silently while serializing TypedActor proxies and ActorRef across 32 bit and 64 bit JVMs

What configuration is required to fix the following problem?
Akka Actor on 64 bit jvm(machine1) CANNOT use TypedActor proxies on the 32 bit jvm(machine2) (CASE1)
but WORKS vice versa (CASE2).
Is there some configuration setting for serialization I'm missing out?
I'm using akka-2.2.1 from java.
I've a small test code which replicates this problem always.
There are no logs which report "ERRORS", despite enabling even remote-lifecycle events.
It just times out when calling registerListener() on CASE1.
I'm clueless, any help/clue is greatly appreciated.
server.java
public class Server implements ServerActor {
public static final String serverActorName = "server";
public static final String serverIP = "192.168.11.112";
public static final int serverPort = 9999;
public static void main(String[] args) {
new Server();
}
ActorSystem serverSystem;
public Server() {
String network = String
.format("akka.actor.provider = \"akka.remote.RemoteActorRefProvider\" \n"
+ "akka.remote.enabled-transports = [\"akka.remote.netty.tcp\"] \n"
+ "akka.remote.netty.tcp.hostname = \"%s\" \n"
+ "akka.remote.netty.tcp.port = %d", Server.serverIP,
Server.serverPort);
Config config = ConfigFactory.parseString("akka.loglevel = DEBUG \n"
+ "akka.actor.debug.lifecycle = on \n" + network);
serverSystem = ActorSystem.create("sys", config);
RemoteActorRefProvider ref = (RemoteActorRefProvider) serverSystem
.provider();
Address addr = ref.transport().defaultAddress();
String port = addr.port().get().toString();
System.out.printf("Server Akka IP=%s PORT=%s\n", addr, port);
final Server server = this;
// start server service
#SuppressWarnings("unused")
ServerActor proxy = TypedActor.get(serverSystem).typedActorOf(
new TypedProps<Server>(ServerActor.class,
new Creator<Server>() {
private static final long serialVersionUID = 6301999771454618282L;
#Override
public Server create() {
return server;
}
}), Server.serverActorName);
}
#Override
public boolean registerListener(ITestListener listener) {
listener.update(10);
return true;
}
}
And client.java
public class Client implements ITestListener {
public static final String clientActorName = "client";
public static final String clientIP = "192.168.11.111";
public static void main(String[] args) {
new Client();
}
ActorSystem clientSystem;
private ITestListener clientListener = null;
public Client() {
String network = String
.format("akka.actor.provider = \"akka.remote.RemoteActorRefProvider\" \n"
+ "akka.remote.enabled-transports = [\"akka.remote.netty.tcp\"] \n"
+ "akka.remote.netty.tcp.hostname = \"%s\" \n"
+ "akka.remote.netty.tcp.port = 0", Client.clientIP);
Config config = ConfigFactory.parseString("akka.loglevel = DEBUG \n"
+ "akka.actor.debug.lifecycle = on \n" + network);
clientSystem = ActorSystem.create("sys", config);
RemoteActorRefProvider ref = (RemoteActorRefProvider) clientSystem
.provider();
Address addr = ref.transport().defaultAddress();
String port = addr.port().get().toString();
System.out.printf("Client Akka IP=%s PORT=%s\n", addr, port);
final Client client = this;
// start server service
clientListener = TypedActor.get(clientSystem).typedActorOf(
new TypedProps<Client>(ITestListener.class,
new Creator<Client>() {
private static final long serialVersionUID = 2034444366744329184L;
#Override
public Client create() {
return client;
}
}), Client.clientActorName);
connect();
}
private void connect() {
// Connect to remote actor system
String remotePath = String.format("akka.tcp://sys#%s:%d/user/%s",
Server.serverIP, Server.serverPort, Server.serverActorName);
// get remote server proxy object
// TypedActor.context().setReceiveTimeout(Duration.create("3 second"));
ActorRef remoteRef = clientSystem.actorFor(remotePath);
if (remoteRef == null)
throw new RuntimeException("Cannot get remote akka actor");
final ServerActor server = TypedActor.get(clientSystem).typedActorOf(
new TypedProps<ServerActor>(ServerActor.class), remoteRef);
server.registerListener(clientListener);
}
#Override
public void update(int a) {
System.out.printf("*********** Server Sent %d ************\n", a);
}
}

how to access the activemq statistics plugin in .net

I am trying to access the activemq statistics information http://activemq.apache.org/statisticsplugin.html in c#
This is what i have so far. I am not able to get a reply from the consumer. I can the count increase in monitor website for the queue.
public class Statistics
{
private readonly string queueName = string.Empty;
private readonly string queueToMonitor = string.Empty;
private readonly IConnectionFactory connectionFactory;
private readonly IConnection connection;
private readonly ISession session;
private readonly IMessageProducer producer;
private readonly ActiveMQQueue queue;
public Statistics(string qName, string brokerUri, string queueToMon)
{
this.queueName = qName;
this.queueToMonitor = "ActiveMQ.Statistics.Destination." + queueToMon;
this.connectionFactory = new ConnectionFactory(brokerUri);
this.connection = connectionFactory.CreateConnection();
this.connection.Start();
this.session = connection.CreateSession();
queue = new ActiveMQQueue(qName);
producer = session.CreateProducer(queue);
}
public void GetStats()
{
try
{
var statusQueue = session.CreateTemporaryQueue();
var consumer = session.CreateConsumer(statusQueue);
ActiveMQQueue query = new ActiveMQQueue(queueToMonitor);
var msg = session.CreateMessage();
msg.NMSReplyTo = statusQueue;
producer.Send(queue, msg);
var reply = (ActiveMQMapMessage)consumer.Receive();
if (reply != null)
{
var test = reply.Content.ToString();
}
}
catch (Exception e)
{
var t = e.Message + " " + e.StackTrace;
}
}
}
You are sending the message to the wrong queue. You need to send the message to the ActiveMQ.Statistics.Destination.QueueToMonitor destination. I re-wrote your GetStats() function to show that it works. The critical change is which destination the producer sends the message to.
public void GetStats()
{
try
{
IDestination statusQueue = session.CreateTemporaryQueue();
IMessageConsumer consumer = session.CreateConsumer(statusQueue);
IDestination query = session.GetQueue(queueToMonitor);
IMessage msg = session.CreateMessage();
IMessageProducer producer = session.CreateProducer(query);
msg.NMSReplyTo = statusQueue;
producer.Send(msg);
IMapMessage reply = (IMapMessage) consumer.Receive();
if(reply != null)
{
IPrimitiveMap statsMap = reply.Body;
foreach(string statKey in statsMap.Keys)
{
Console.WriteLine("{0} = {1}", statKey, statsMap[statKey]);
}
}
}
catch(Exception e)
{
var t = e.Message + " " + e.StackTrace;
}
}

How can I use WCF instead of manual C# using tcplistenr?

I have the following code and was wondering if there is a benefit to moving this to WCF?
Basically, I am listening for smtp messages over some port and use thread pooling to parse each tcp connection asynchronously.
static void Main(string[] args)
{
try
{
TcpListener listener = new TcpListener(IPAddress.Any, 8000);
TcpClient client;
listener.Start();
while (true) // Add your exit flag here
{
client = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(ThreadProc, client);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}//Main
private static void ThreadProc(object obj)
{
var client = (TcpClient)obj;
// Do your work here...
NetworkStream ns = client.GetStream();
using (StreamWriter writer = new StreamWriter(ns))
{
writer.WriteLine("220 SMTP server ready.");
writer.Flush();
using (StreamReader reader = new StreamReader(ns))
{
//parse + persist smtp message here...
}
}
}//ThreadProc