I have been tring to set up a UDP client/server in windows .net sockets.
In the client script below I am able to send a message to the server when the client "connects", but I get a null reference when I try to call the BeginToReceeve() function.
I am confused as to why I can send a message (using the server endpoint of course), but not receive because of a null error. I am new to sockets and am wondering why this is not working?
The server is a running in a windows c# application, and the client is running in a c# script in Unity3D.
private EndPoint epServer;
private Socket clientSocket;
private byte[] myBuffer = new byte[1024];
private void ConnectToServer ( ) {
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint server = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 61456);//Connect to the Local server
epServer = (EndPoint)server; //Access the server
WritePacketAndSend("Hello Server");//This creates the packet and uses the BeginToSend() function to send the string to the server
try{
clientSocket.BeginReceiveFrom(myBuffer, 0, myBuffer.Length, SocketFlags.None, ref epServer, new AsyncCallback(ReceiveData), epServer);//<<< Null reference here not sure why...
} catch(Exception ex) {
print(ex.Message); //Keep getting: Object reference not set to an instance of an object
}
}
private void ReceiveData(IAsyncResult ar){
print("Entered ReceiveData");//The code never enters here
try{
IPEndPoint server = new IPEndPoint(IPAddress.Parse("127.0.0.1", 61456);
epServer = (EndPoint)server;
clientSocket.EndReceiveFrom(ar, ref epServer);
clientSocket.EndReceive(ar);
print(Encoding.UTF8.GetBytes(myBuffer));
clientSocket.BeginReceiveFrom(myBuffer, 0, myBuffer.Length, SocketFlags.None, ref epServer, new AsyncCallback(ReceiveData), epServer,
} catch (Exception ex){
print("Receive Data: " + ex.Message);
}
}
Related
I want to handle multiple client's request concurrently using Socket Server.
i have 10 clients, which can send request to my server at same time.
How could i handle this?
Is it possible?
With below code, i can handle only one request at a time, after completion of the request, server accepts next request.
Due to this 10th client need to wait until 9 requests get complete.
Any help would be appreciated
Below is the code i am using for Server Socket
Socket _serverSocket;
byte[] _buffer = new byte[255];
void SetupServer()
{
try
{
Console.WriteLine ("Setting up server...");
IPEndPoint ipEndPoint = new IPEndPoint (IPAddress.Parse(_ip), _port);
// create server socket to listen new client's connection
_serverSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind (ipEndPoint);
_serverSocket.Listen (100);
_serverSocket.BeginAccept (new AsyncCallback (AcceptCallback), null);
}
catch (System.Exception ex)
{
Console.WriteLine ("Server failed :: {0}", ex.Message);
}
}
void AcceptCallback(IAsyncResult ar)
{
Socket clientSocket = _serverSocket.EndAccept(ar);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), clientSocket);
}
void RecieveCallback(IAsyncResult ar)
{
Socket clientSocket = (Socket)ar.AsyncState;
int received = clientSocket.EndReceive(ar);
// check if client is disconnected?
if (received == 0)
{
Console.WriteLine("client is disconnected...");
return;
}
// do whatever you want with received data here...
byte[] dataBuf = new byte[received];
Array.Copy(_buffer, dataBuf, received);
string text = Encoding.ASCII.GetString(dataBuf);
Console.WriteLine("Received Data: {0}", text);
// accept new request
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), clientSocket);
}
You should familiarize yourself with the concept of a "multi threaded server". You should start a thread for each client which connects to the server. So you can simultaneously handle multiple clients. Or you could use Tasks Parallel Library if you want to try newer .NET features.
But there are many examples out there in the web that describe how to implement such a server.
I've been working on a socket server program in C# (I was inspired from this post) and my problem is that when a client disconnects an exception "An existing connection was forcibly closed by the remote host" appears when the call EndReceiveFrom() and returns 0, the ref clientEP becomes the client normally close. I don't understand why my DoReceiveFrom() function is called if there is nothing to read. I probably missed something. What is wrong ?
Problem appear there :
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
The full source code:
class UDPServer
{
private Socket serverSocket = null;
private List<EndPoint> clientList = new List<EndPoint>();
private List<Tuple<EndPoint, byte[]>> dataList = new List<Tuple<EndPoint, byte[]>>();
private byte[] byteData = new byte[1024];
private int port = 4242;
public List<Tuple<EndPoint, byte[]>> DataList
{
private set { this.dataList = value; }
get { return (this.dataList); }
}
public UDPServer(int port)
{
this.port = port;
}
public void Start()
{
this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.serverSocket.Bind(new IPEndPoint(IPAddress.Any, this.port));
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
byte[] data = new byte[dataLen];
Array.Copy(this.byteData, data, dataLen);
if (!this.clientList.Any(client => client.Equals(clientEP)))
this.clientList.Add(clientEP);
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
DataList.Add(Tuple.Create(clientEP, data));
}
catch (ObjectDisposedException)
{
}
}
public void SendTo(byte[] data, EndPoint clientEP)
{
try
{
this.serverSocket.SendTo(data, clientEP);
}
catch (System.Net.Sockets.SocketException)
{
this.clientList.Remove(clientEP);
}
}
public void SendToAll(byte[] data)
{
foreach (var client in this.clientList)
{
this.SendTo(data, client);
}
}
public void Stop()
{
this.serverSocket.Close();
this.serverSocket = null;
this.dataList.Clear();
this.clientList.Clear();
}
}
Exception:
An existing connection was forcibly closed by the remote host
Update:
I tried to run my client (netcat) on another pc and the exception no longer appears, even when SendTo(), which is also problematic to delete my client in my clientList.
I still do not understand what is happening.
Everything is as it should be.
This is the way all Async methods work: you invoke BeginDo() and pass into it your implementation of AsyncCallback delegate (in your example that's DoReceiveFrom). You implementation starts executing immediately after that - BeginDo() is not a blocking call.
Inside your implementation, you must call EndDo(), which will block until one of two things happen: the object, on which you invoked BeginDo(), actually does something, or it throws an exception doing it. As it does in your case when client disconnects.
The source on the Async method.
What you need to do for the whole thing to work is
Make sure that you handle that client-disconnected exception properly
Make sure that you call BeginReceiveFrom regardless of the way EndReceiveFrom finishes. And preferably, call BeginReceiveFrom immediately after you call EndReceiveFrom. This is needed because while you server is in-between those calls, it does not actually listen to the socket.
I would put another try-catch around EndReceiveFrom.
UPDATE:
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = 0;
byte[] data = null;
try
{
dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
data = new byte[dataLen];
Array.Copy(this.byteData, data, dataLen);
}
catch(Exception e)
{
}
finally
{
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
if (!this.clientList.Any(client => client.Equals(clientEP)))
this.clientList.Add(clientEP);
DataList.Add(Tuple.Create(clientEP, data));
}
catch (ObjectDisposedException)
{
}
}
The following code sends a packet on port 15000:
int port = 15000;
UdpClient udp = new UdpClient();
//udp.EnableBroadcast = true; //This was suggested in a now deleted answer
IPEndPoint groupEP = new IPEndPoint(IPAddress.Broadcast, port);
string str4 = "I want to receive this!";
byte[] sendBytes4 = Encoding.ASCII.GetBytes(str4);
udp.Send(sendBytes4, sendBytes4.Length, groupEP);
udp.Close();
However, it's kind of useless if I can't then receive it on another computer. All I need is to send a command to another computer on the LAN, and for it to receive it and do something.
Without using a Pcap library, is there any way I can accomplish this? The computer my program is communicating with is Windows XP 32-bit, and the sending computer is Windows 7 64-bit, if it makes a difference. I've looked into various net send commands, but I can't figure them out.
I also have access to the computer (the XP one)'s local IP, by being able to physically type 'ipconfig' on it.
EDIT: Here's the Receive function I'm using, copied from somewhere:
public void ReceiveBroadcast(int port)
{
Debug.WriteLine("Trying to receive...");
UdpClient client = null;
try
{
client = new UdpClient(port);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
IPEndPoint server = new IPEndPoint(IPAddress.Broadcast, port);
byte[] packet = client.Receive(ref server);
Debug.WriteLine(Encoding.ASCII.GetString(packet));
}
I'm calling ReceiveBroadcast(15000) but there's no output at all.
Here is the simple version of Server and Client to send/receive UDP packets
Server
IPEndPoint ServerEndPoint= new IPEndPoint(IPAddress.Any,9050);
Socket WinSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
WinSocket.Bind(ServerEndPoint);
Console.Write("Waiting for client");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0)
EndPoint Remote = (EndPoint)(sender);
int recv = WinSocket.ReceiveFrom(data, ref Remote);
Console.WriteLine("Message received from {0}:", Remote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Client
IPEndPoint RemoteEndPoint= new IPEndPoint(
IPAddress.Parse("ServerHostName"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
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
I have a simple C#/.NET 3.5 client/server apps I am trying to write to get a handle on how to communicate in UDP. I am able to get the sync methods working and sending data back and forth, but now I am trying to switch to the async methods and I keep getting the error, "The requested address is not valid in it's context."
My Client code is as follows:
IPEndPoint ipep = new IPEndPoint(ipaddr, ipport);
newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint remote1 = (EndPoint)ipep;
AddMessage("Looking for connections");
byte[] strt = Encoding.ASCII.GetBytes("open");
newsock.SendTo(strt,remote1);//.BeginSendTo(strt, 0, strt.Length, SocketFlags.None, remote1, new AsyncCallback(OnSend), null);
IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 0);
EndPoint epSender = (EndPoint)ipeSender;
newsock.ReceiveFrom(rcv, ref epSender);
My Server is more complicated, as I have already switched to Async communication.
In a worker thread I call:
try
{
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint remote = (EndPoint)sender;
AddMessage("Beginning Wait for connections");
newsock.BeginReceiveFrom(rcv, 0, rcv.Length, SocketFlags.None, ref remote, new AsyncCallback(OnReceive), null);
while (true)
{
if (pleasestop.WaitOne(20))
break;
ts = DateTime.Now - lastnoop;
if (senddata)
{
//...fill sending byte array...
IPEndPoint ipep = new IPEndPoint(IPAddress.Any,0);//ipaddr, ipport);
EndPoint remote1 = (EndPoint)ipep;
newsock.BeginSendTo(sending, 0, sending.Length, SocketFlags.None, remote1, new AsyncCallback(OnSend), null);
}
}
In my OnSend callback function is where I get the error: "The requested address is not valid in it's context."
private void OnSend(IAsyncResult ar)
{
try
{
newsock.EndSendTo(ar);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace, "Server Send Error");
}
}
I dont think the object state can be null, try this:
newsock.BeginSendTo(sending, 0, sending.Length, SocketFlags.None,
remote1, new AsyncCallback(OnSend), newsock);
I found my problem. I wasn't using the correct EndPoint in my server to send a response back to my client.
In my receive callbackup function I now use mySender, which is a SendPoint defined at the class level. I then use this to send a response back to my client.
newsock.EndReceiveFrom(ar, ref mySender);
newsock.BeginSendTo(sending, 0, sending.Length, SocketFlags.None, mySender, new AsyncCallback(OnSend), mySender);
My app is now working correctly.