So here's the thing, i'm creating a server/client environment for a game where a port forwarded computer acts as a server, and clients send the first UDP message to connect and get the accept message then start sending the in-game UDP messages after successfully connecting.
The problem is, when I use the local IPs say the server using 10.0.0.7 and a client is using 10.0.0.4, everything works just fine:
Client sends connect message.
Server receives it.
Servers sends back accept message.
Client receives it
All further messages reach both ends without any problem.
But when I use the external IP:
Client sends connect message.
Server receives it.
Servers sends back accept message.
Client receives it
Both ends can send messages but the client doesn't receive any more messages.
Wanted to know at the end if the problem is somehow from the code, or from what I think it's really from, router, NAT, firewalls or anything like that.
(Note: Client sends to server's 8888 port, and server sends back through the client's local port, as it should be.)
Below is the client code, written for Unity:
void Start()
{
client = new UdpClient();
client.Connect(IPAddress.Parse("<Global IP>"), 8888);
client.BeginReceive(new AsyncCallback(ReadMessage), client);
}
private void ReadMessage(IAsyncResult result)
{
IPEndPoint ipEndPoint = null;
string message = Encoding.ASCII.GetString(client.EndReceive(result, ref ipEndPoint));
print("Got: " + message);
string[] wholeMessages = message.Split('#');
for (int w = 0; w < wholeMessages.Length - 1; w++)
{
string[] parts = wholeMessages[w].Split('$');
if (!connected && parts.Length == 3 && parts[0] == "accept" && int.TryParse(parts[1], out ID))
{
connected = true;
code = parts[2];
}
}
client.BeginReceive(new AsyncCallback(ReadMessage), client);
}
public void SendUDP(string message)
{
client.Send(Encoding.ASCII.GetBytes(message), message.Length);
}
Ok, after several trials and errors this worked for me...
//Server Code
private static UdpClient udpClient;
static void Main(string[] args)
{
Console.WriteLine("Server initiated...");
udpClient = new UdpClient(8888);
}
private static void ReadMessage()
{
while (true)
{
try
{
IPEndPoint IPEP = null;
string message = Encoding.ASCII.GetString(udpClient.Receive(ref IPEP));
}
}
}
private static void SendUDP(IPEndPoint e,string message)
{
new UdpClient().Send(Encoding.ASCII.GetBytes(message), message.Length, e);
}
//Client Code
private IPAddress ip;
void Start()
{
ip = Dns.GetHostAddresses("HOSTNAME")[0];
client = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
udpThread = new Thread(new ThreadStart(ReadMessage))
{
IsBackground = true
};
udpThread.Start();
}
private void ReadMessage()
{
while (true)
{
try
{
IPEndPoint IPEP = null;
byte[] data = client.Receive(ref IPEP);
string message = Encoding.ASCII.GetString(data);
}
}
}
public void SendUDP(string message)
{
client.Send(Encoding.ASCII.GetBytes(message), message.Length, new IPEndPoint(ip, 8888));
}
Related
The case for my problem is: There is a program running locally acting like a server sending data on request. I can call for data on port 4096.
I would like to create client side which would send the message requested by the "server" ("GET_DATA") and then listen for whole response (several chunks). Then, after validating wholeness
of the data (CheckCompleteData method) or some time, send request "GET_DATA" again and keep listening for the response.
My code so far:
public class Connector
{
private static UdpClient udpClient;
private static List<Byte[]> receivedData;
readonly Byte[] sendBytes = Encoding.ASCII.GetBytes("GET_DATA");
private static IPEndPoint ep;
public Connector(string address, int port, int bufferSize)
{
if (String.IsNullOrEmpty(address))
{
throw new ArgumentNullException();
}
udpClient = new UdpClient();
udpClient.Client.ReceiveBufferSize = bufferSize;
ep = new IPEndPoint(IPAddress.Parse(address), port);
udpClient.Connect(ep);
}
private void SendDataRequest()
{
udpClient.Send(sendBytes, sendBytes.Length);
}
public List<Byte[]> ReceiveAllData()
{
SendDataRequest();
receivedData = new List<byte[]>();
udpClient.BeginReceive(new AsyncCallback(ReceiveData), null);
return receivedData;
}
private static void ReceiveData(IAsyncResult res)
{
receivedData.Add(udpClient.EndReceive(res, ref ep));
udpClient.BeginReceive(ReceiveData, null);
}
}
So far I managed to receive all chunks of one message, but I cannot call ReceiveAllData repeatedly, because the client is already disposed.
I have no idea how to secure continuous listening with calling some event when data received.
Any suggestions ?
So I'm trying to create a chat application but I'm new to sockets. I have followed a tutorial to create a server and client, however, the server does not broadcast the data sent from one client to every client connected to it. Instead, it only broadcasts it to the client that sent the data.
I have tried to add every client who joins the server to a list and then use a foreach loop to send the data received from one client to every client in the list. This, however, has not worked. I suspect that the error is in the foreach loop but I am not completely certain.
Here is my code for the server:
class Program
{
public static List<Socket> connectedClient = new List<Socket>();
public static Socket clientSocket = default(Socket);
static void Main(string[] args)
{
int port = 13000;
string IpAddress = "127.0.0.1";
Socket serverListener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(IpAddress), port);
serverListener.Bind(ep);
serverListener.Listen(0);
Console.WriteLine("Server running");
Program p = new Program();
int counter = 0;
while (true)
{
counter++;
clientSocket = serverListener.Accept();
connectedClient.Add(clientSocket);
Console.WriteLine(counter + " Client joined");
Thread clientThread = new Thread(new ThreadStart(() =>
p.User(clientSocket)));
clientThread.Start();
}
}
public void User(Socket client)
{
while (true)
{
byte[] msg = new byte[1024];
int size = client.Receive(msg);
Console.WriteLine("Client>> " +
System.Text.Encoding.ASCII.GetString(msg, 0, size));
//the loop that i tried to implement
foreach(Socket clientSocket in connectedClient)
{
client.Send(msg, 0, size, SocketFlags.None);
}
}
}
}
Instead of the message being broadcasted once to all clients, the server sends the message back to the client who sent it but times how many clients there are.
For example: If there are 4 clients connected to the server and one client sends a message "Hello" the server will send back "HelloHelloHelloHello" but only to the client who sent the "Hello".
In
foreach(Socket clientSocket in connectedClient)
{
client.Send(msg, 0, size, SocketFlags.None);
}
You are looping over the clientSockets, but you are Sending on the client, not the clientSocket. If you do clientSocket.Send instead, you should get the expected behavior (e.g. send to each client instead of to one client 4 times).
I have been experimenting with some code to find other computer's on my network running my app. Firstly I broadcast and listen for those broadcasts. After that I am a little lost on the next step. Once Computer A knows the ip address of Computer B because of the broadcast how do I put Computer B in a state to accept socket connections. Then how does Computer A begin that connection?
Also I have tried doing the broadcasting with Multicast and cannot get that to work. If anyone has extra time could they show that as well.
Starting Listener and Sender:
private static void StartServer()
{
Task.Factory.StartNew(async () =>
{
await StartListeningAsync();
});
}
private static void StartClient()
{
Task.Factory.StartNew(async () =>
{
await StartSendingAsync();
});
}
Those inner methods:
private static async Task StartSendingAsync()
{
try
{
using (UdpClient _broadcaster = new UdpClient())
{
var ipHost = Dns.GetHostEntry("");
var ipAddr = ipHost.AddressList[ipHost.AddressList.Count() - 1];
IPEndPoint ip = new IPEndPoint(IPAddress.Broadcast, PORT);
var ipAddress = Encoding.ASCII.GetBytes(ipAddr.ToString());
for (int x = 0; x < 10; x++)
{
_broadcaster.Send(ipAddress, ipAddress.Count(), ip);
await Task.Delay(TimeSpan.FromSeconds(6));
}
}
}
catch (Exception ex)
{
}
}
private static async Task StartListeningAsync()
{
while (true)
{
using (UdpClient _listener = new UdpClient(PORT))
{
try
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT);
var incoming = await _listener.ReceiveAsync();
NewPing(incoming.Buffer, incoming.RemoteEndPoint);
await Task.Delay(TimeSpan.FromSeconds(10));
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.TimedOut)
{
//Time out that's fine
}
}
}
}
}
What happens when the listener hears a broadcast:
private static void NewPing(byte[] incoming, IPEndPoint rem)
{
Console.WriteLine($"New ping from {rem.ToString()}, attempting to connect!");
//What should happen here now that one of the computer's know the other exists?
//Start some kind of Socket Accepting method?
}
If I understand correctly, you want a machine to send out a UDP broadcast, and then establish a TCP connection between the two?
I'd perform the following steps:
B is listening for UDP broadcasts
A wants a TCP connection with B, so
A starts listening for incoming TCP connections
A sends out a broadcast saying "I'm listening"
B receives the broadcast and attempts to connect to A
I've created two sample console applications, one server, one client:
Server:
using System;
using System.Net;
using System.Net.Sockets;
class Program
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, 11220));
listener.Start();
listener.AcceptSocketAsync().ContinueWith((t) => HandleClient(t.Result));
Console.WriteLine($"Listening for TCP connections at port 11220...");
using (UdpClient broadcaster = new UdpClient(AddressFamily.InterNetwork))
{
broadcaster.EnableBroadcast = true;
Console.WriteLine("Broadcasting...");
broadcaster.Send(new byte[] { 1, 2, 3 }, 3, new IPEndPoint(IPAddress.Broadcast, 11221));
}
while (Console.ReadKey(true).Key != ConsoleKey.Q)
{
Console.WriteLine("Press 'Q' to quit");
}
}
static void HandleClient(Socket socket)
{
Console.WriteLine($"TCP connection accepted ({socket.RemoteEndPoint})!");
}
}
Client:
using System;
using System.Net;
using System.Net.Sockets;
class Program
{
static void Main(string[] args)
{
using (UdpClient client = new UdpClient(11221, AddressFamily.InterNetwork))
{
Console.WriteLine("Waiting for broadcast...");
client.EnableBroadcast = true;
client.ReceiveAsync().ContinueWith((t) => HandleBroadcast(t.Result)).Wait();
}
Console.WriteLine("Press any key to continue");
Console.ReadKey(true);
}
static void HandleBroadcast(UdpReceiveResult result)
{
Console.WriteLine($"Received broadcast from {result.RemoteEndPoint}, attempting to connect via TCP");
Socket socket = new Socket(result.RemoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(result.RemoteEndPoint.Address, 11220));
}
}
First start the client, then the server. The data sent in the broadcast is just dummy data, but you could include some information like the TCP port number the server is listening at.
PS. Remember that this is just a proof of concept.
I got into UDP and decided to make a small chat just for practice.
I ran into a problem and I can't figure it out myself.
I created two c# console Programs which are exactly the same (Just Port is different)
I send a UDP broadcast package and then want to receive it on the second console program. What happens tho is that the program I send the broadcast from receives it and the other program doesn't. Same happens at the other way round.
I already switched off my firewall --> doesn't change anything.
I post you the whole code, I hope you guys can help me I would really love to keep going! Thank you so much!
class Program
{
const int PORT = 10101;
private static readonly UdpClient udpclient = new UdpClient(PORT);
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Red;
udpclient.EnableBroadcast = true;
//bool for calling async receiver just once
bool receiving = false;
Console.WriteLine("Chat 2");
//to keep while loop running --> change later
bool keepchatting = true;
#region keepchating loop
while (keepchatting)
{
if (!receiving)
{
startlistening();
}
receiving = true;
newmessage();
}
}
#endregion
//new message --> call sendmessage to broadcast text via UDP
public static void newmessage()
{
string msg;
msg = Console.ReadLine();
byte[] message = Encoding.ASCII.GetBytes(msg);
sendmessage(message);
}
//Broadcast text via UDP
public static void sendmessage(byte[] tosend)
{
UdpClient client = new UdpClient();
client.EnableBroadcast = true;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT);
client.Send(tosend, tosend.Length, ip);
client.Close();
Console.WriteLine("Sent!");
}
static IAsyncResult ar = null;
//Setup Async Receive Method
public static void startlistening()
{
ar = udpclient.BeginReceive(RecievedMessage, new object());
}
//Message
public static void RecievedMessage(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, PORT);
byte[] bytes = udpclient.EndReceive(ar, ref ip);
string msg = Encoding.ASCII.GetString(bytes);
Console.WriteLine("Received: " + msg);
startlistening();
}
}
I have changed only two parts to your code, on each client set the remote port number of the other client, try this:
On one client:
const int PORT = 10101;
const int PORT_Remote = 10102;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT_Remote);
On the other client:
const int PORT = 10102;
const int PORT_Remote = 10101;
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("255.255.255.255"), PORT_Remote);
I've wrote an application recently where I was sending socket messages back and forth between two applications on my laptop. I used 127.0.0.1 (default IP address for local host) for the IP address. Could you try that?
Iam trying to send a message (via UDP) from my client to my server. The server should answer this message and if the client receives this answer he should print out a message.
If i run the client and server on my local network everything works fine.
If i try to connect through the internet from another PC outside my network the server receives the request of the client, sends an answer back, but the client never receives this answer. The client and the server are both behind a NAT but i portforwarded the ports at the server´s NAT and the server got its own DNS. I already tried NAT traversal but it gives me the same IP and port adress as the IPEndPoint of the server, after receiveing the request of the client, does.
I´ve got no idea how to fix this, so any guidance would be much appreciated.
Client
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
object[] oData = {1};
sendData(oData, 0,0, "Li");
while (true)
{
Console.ReadLine();
}
}
private void receiveData()
{
string receivePort = 8080;
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.ReceiveTimeout = 1000;
IPEndPoint end = new IPEndPoint(IPAddress.Any, receivePort);
client.Bind(end);
while (true)
{
try
{
byte[] data = new byte[1024];
client.Receive(data, 0, data.Length, SocketFlags.None);
object[] receivedObj = Deserialize(data);
string sType = (string)receivedObj[3];
if (sType == "Li")
{
console.WriteLine("received Li");
}
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
public static void sendData(object[] oData, int iFrom, int iTo, string sType)
{
string sendPort = 17171;
UdpClient client = new UdpClient();
string IP = "ThisIsTheDNSofmyServer.com"; //ServerDNS
//string IP = "192.168.xxx.xxx"; //serverIP in LAN
if (IP.StartsWith("T"))
{
IP = (Dns.GetHostAddresses(IP))[0].ToString();
}
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
oData[1] = iFrom;
oData[2] = iTo;
oData[3] = sType;
Byte[] data = Serialize(oData);
client.Send(data, data.Length, remoteEndPoint);
}
The server´s code is almost the same:
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
while (true)
{
Console.ReadLine();
}
}
private static void ReceiveData()
{
int receivePort = 17171;
UdpClient client = new UdpClient(receivePort);
while (true)
{
try
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
data = client.Receive(ref anyIP);
object[] receivedObj = Deserialize(data);
//if I receive data send an Answer
sendData(receivedObj, 0,0,"Li",anyIP.Address.ToString());
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
private static void sendData(object[] oData, int iFrom, int iTo, string sType, string IP)
{
int sendPort = 8080;
object[] paket = { oData, iFrom, iTo, sType };
UdpClient client = new UdpClient();
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
client.Send(data, data.Length, remoteEndPoint);
}
i believe this is a port cofniguration issue,
8080 is almost likely to be configured as alternate http
"The UdpClient you use to receive datagrams must be created using the multicast port number" from MSDN
Hope this helps and good luck
Krishna
You do not need to do anything unordinary to traverse NAT in the setup you described, you just need to send it from the server back to your client; specifically: you must send back to the end point, i.e. IP and port, you received it on.
client.Send(data, data.Length, remoteEndPoint); // remoteEndPoint is the IPEndPoint you got the datagram on