udp client bind - c#

I have UDP client chat, which sends messages to the server and get the responses back. I have two threads, one for sending, one for receiving messages. I get the exception with ReceiveFrom() method: "You must call the Bind method before performing this operation". But this is a client, I don't want to bind anything. For example this client works fine:
byte[] data = new byte[30];
string input, stringData;
IPEndPoint servIPEP = new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
EndPoint servEP = (EndPoint)servIPEP;
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
client.SendTo(data, data.Length, SocketFlags.None, servEP);
data = new byte[30];
int recv = client.ReceiveFrom(data, ref servEP); //works fine!
There is no bind for receiving. But when I create two threads error is thrown:
public ChatClient()
{
clientSock = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
servIPEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 32000);
servEP = (EndPoint)servIPEP;
}
public void ReceiveThread()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
}
public void ReceiveData()
{
while(true){
clientSock.ReceiveFrom(buf, ref servEP); //Here I get ERROR
string msg = Encoding.ASCII.GetString(buf).Trim();
Console.WriteLine("New message: {0}",msg);
}
}
public void SendThread()
{
Thread sendThread = new Thread(new ThreadStart(SendData));
sendThread.Start();
}
public void SendData()
{
while (true)
{
Console.WriteLine("Enter message to send: ");
string msg = Console.ReadLine();
buf = Encoding.UTF8.GetBytes(msg);
clientSock.SendTo(buf, servEP);
}
}
}
static void Main(string[] args)
{
ChatClient client = new ChatClient();
client.SendThread();
client.ReceiveThread();
}
}
Thank you for your time.

Clearly SendTo() does an implicit bind, and ReceiveFrom() doesn't.
It doesn't make much sense to start receiving without a prior bind to at least set the port number you're receiving via. Otherwise how would you expect to get any data?

Related

Send and receive data in c# network programming winform

I have a small server that is received and sends the message back to the client.
this is the client-side
when I open the client it will connect to server through Connect()
public Form1()
{
InitializeComponent();
Connect();
CheckForIllegalCrossThreadCalls = false;
}
this is my connect
void Connect()
{
ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999);
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
MessageBox.Show(Convert.ToString(e));
}
Thread listen = new Thread(Receive);
listen.IsBackground = true; ;
listen.Start();
}
and I have a receive like this
void Receive()
{
datarec = new byte[1024];
try
{
while (true)
{
string StringData;
rec = server.Receive(datarec);
StringData = Encoding.ASCII.GetString(data, 0, rec);
txtShow.Text = StringData;
}
}
catch
{
Close();
}
}
and I send data through a button have Send method
void Send(string s)
{
data = new byte[1024];
data = Encoding.ASCII.GetBytes(s);
server.Send(data, data.Length, SocketFlags.None);
}
Send button
private void button1_Click(object sender, EventArgs e)
{
string s = txtText.Text;
Send(s);
}
this is the server-side
I have a thread server
public static void Process(Socket client)
{
byte[] data = new byte[1024];
int recv;
string dataInput;
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
while (true)
{
try
{
recv = client.Receive(data);
dataInput = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(dataInput);
client.Send(data);
}
catch (SocketException e)
{
Console.WriteLine(e);
}
}
}
this is the server main
public static void Main()
{
byte[] rec = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9999);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(ipep);
server.Listen(10);
Console.WriteLine("Waiting for client...");
Console.WriteLine("LOG CHAT");
while (true)
{
Socket client = server.Accept();
Core core = new Core();
Thread t = new Thread(() => Core.Process(client));
t.Start();
}
}
the server receive message but when it sends a message back it has an error "An established connection was aborted by the software in your host machine"
Can you guys tell me where I was wrong and how can I fix it?
When you call client.Send(data) in your server code, you will send the whole 1024 byte buffer back to the client, not just the data received.
Encoding.ASCII.GetString in the client could fail when processing this garbage and the exception will close the connection.
Try to replace client.Send(data) by client.Send(data, recv, SocketFlags.None).
Also, you should not update UI controls directly from a background thread, Use Control.Invoke for this. Failing to do so will also throw an exception and close the connection.

CSharp async server program immediately closes at start

im pretty to new to programming and i've just now wrote my first async server, but as soon as i start the program, it closes right after writing waiting for new client, can someone help me out? I dont know what stupid thing im doing.
I have a class UDPServer with some methods, of which
- UDPServer() receives an ipendpoint of the localserver ipaddress and port to initialize stuff (called in main to create a new UDP server object)
- right after that i call the get connection method, which supposedly should make the server wait for a new client, but instead it immediately closes.
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket clientSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
class UDPServer
{
Socket serverSocket;
IPEndPoint localIPEP;
IPEndPoint senderIPEP;
EndPoint sender;
IPEndPoint[,] playerList;
int playerListIndex;
bool waitingForSecondClient;
public UDPServer(IPEndPoint serverIpEndPoint)
{
localIPEP = serverIpEndPoint;
serverSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
serverSocket.Bind(localIPEP);
senderIPEP = new IPEndPoint(IPAddress.Any, 0);
sender = senderIPEP;
playerList = new IPEndPoint[5000, 2]; // 5000 possible player lobbies, each with 2 player ip addresses and ports
playerListIndex = 0; // we start filling up the lobbies from 0
Console.WriteLine("Server setup complete.");
}
public void GetConnection()
{
StateObject state = new StateObject();
Console.WriteLine("Waiting for new client.");
serverSocket.BeginReceiveFrom(state.buffer, 0, StateObject.BufferSize, SocketFlags.None,ref sender, ClientConnected, state);
}
public void ClientConnected(IAsyncResult asyncResult)
{
StateObject state = (StateObject)asyncResult;
EndPoint remote = state.clientSocket.LocalEndPoint;
StateObject tempState = new StateObject();
int bytesReceived = serverSocket.EndReceiveFrom(asyncResult, ref remote);
serverSocket.BeginReceiveFrom(tempState.buffer, 0, StateObject.BufferSize, SocketFlags.None, ref remote, ClientConnected, tempState);
Console.WriteLine("-------------");
Console.WriteLine("Received bytes of data: " + bytesReceived);
Console.WriteLine("-------------");
Console.WriteLine("Received string: " + state.sb.ToString());
Console.WriteLine("-------------");
if (state.sb.ToString().Equals("New client"))
{
Send(state.clientSocket, "Hello");
}
}
private void Send(Socket client,string message)
{
EndPoint remote = client.LocalEndPoint;
StateObject state = new StateObject();
// Begin sending the data to the remote device.
serverSocket.BeginSendTo(state.buffer, 0, StateObject.BufferSize, 0,remote,SendCallback,state);
}
private static void SendCallback(IAsyncResult asyncResult)
{
// Retrieve the socket from the state object.
Socket client = (Socket)asyncResult.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSendTo(asyncResult);
}
static void Main(string[] args)
{
UDPServer server = new UDPServer(new IPEndPoint(IPAddress.Any, 9050));
server.GetConnection();
}
}
BeginReceiveFrom Does not block, as such program execution reaches the end of your main method and finishes. I am not sure what you intend your exit condition to be, but you will need some sort of code making sure the server waits until that exit condition is met before finishing program execution.

Getting multicast messages with UDPClient

I've got a product plugged directly into the ethernet port of my computer, sending multicast packets to 224.224.10.10 and UDP port 24588. I've set up my UDPclient in the code below, and I feel like I have it set up correctly, but I still don't receive any packets. I always catch an exception saying that I timed out waiting for a response. Any thoughts or glaring mistakes?
I looked at a lot of questions before posting this, but I couldn't get a resolution, and I couldn't find anyone who had the same type of setup that I have.
public class ReceiverClass
{
private UdpClient m_UDPClient = null;
private Thread m_UDPReceiverThread = null;
private bool m_ContinueReceiving = false;
private readonly object m_sync = new object();
private const int UDP_PORT = 24588;
public ReceiverClass()
{
m_ContinueReceiving = true;
m_UDPClient = new UdpClient(UDP_PORT);
m_UDPClient.Client.ReceiveTimeout = 20000;
m_UDPReceiverThread = new Thread(ReceiveData) { IsBackground = true };
m_UDPReceiverThread.Start();
}
private void ReceiveData()
{
bool Continue;
byte[] ReceiveBuffer;
IPEndPoint defaultIP = new IPEndPoint(IPAddress.Any, 0);
m_UDPClient.JoinMulticastGroup(IPAddress.Parse("224.224.10.10"));
m_UDPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
lock (m_sync)
{
Continue = m_ContinueReceiving;
}
while (Continue)
{
try
{
ReceiveBuffer = m_UDPClient.Receive(ref defaultIP);
if (null != ReceiveBuffer)
{
// Do stuff with received...
}
}
catch (Exception e)
{
// ooo eee kill stream
Dispose(false);
return;
}
finally
{
lock (m_sync)
{
Continue = m_ContinueReceiving;
}
}
}
}
}
I can't see anything immediately wrong with your code so I don't have a proper answer for you. However, here's a piece of code I'm using to get UDP broadcast messages. Hopefully it will work for you, or give you some new ideas:
class UdpHandler {
public UdpHandler(int portNo) {
Thread t = new Thread(ListenThread);
t.IsBackground = true;
t.Start(portNo);
}
public void ListenThread(object portNo) {
UdpClient client = new UdpClient { ExclusiveAddressUse = false };
IPEndPoint localEp = new IPEndPoint(IPAddress.Any, (int)port);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
client.Client.Bind(localEp);
while (true) {
byte[] data = client.Receive(ref localEp);
DataReceived(data);
}
}
private void DataReceived(byte[] rawData) {
// Handle the received data
}
}
What I ended up doing was going to the Sockets class and looking at the raw packets and picking out what I needed. I bind the socket to my lan interface, and sniff stuff out. I had to run it as an administrator in order to get it to work, but thats fine. I went this route because I could see the packets in wireshark, but they weren't getting to my udpclient. This ended up being the fastest way to get what I wanted.
Socket ReceiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
EndPoint DefaultIPEndpoint = new IPEndPoint(IPAddress.Parse("10.0.2.0"), 0);
ReceiveSocket.ReceiveTimeout = 5000;
ReceiveSocket.Bind(DefaultIPEndpoint);
ReceiveSocket.IOControl(IOControlCode.ReceiveAll, new byte[4] { 1, 0, 0, 0 }, null);
while (true)
{
byte[] ReceiveBuffer = new byte[512];
int ByteCount = 0;
ByteCount = ReceiveSocket.ReceiveFrom(ReceiveBuffer, ref DefaultIPEndpoint);
// Handle packets ...
}

C# UDP Broadcast and receive example

Problem:
I am trying to bind a udp socket on a specific address. I will broadcast out a message. That same socket will need to be able to receive messages.
Current code:
static void Main()
{
UdpClient Configuration = new UdpClient(new IPEndPoint(IPAddress.Parse(data.IPAddress), configuration.Port)); //set up the bind to the local IP address of my choosing
ConfigurationServer.EnableBroadcast = true;
Configuration.Connect(new IPEndpoint(IPAddress.Parse(data.BroadcastIP), configuration.Port);
Listen();
}
private void Listen()
{
Task.Run(async () =>
{
while (true)
{
var remoteIp = new IPEndPoint(IPAddress.Any, configuration.Port);
var data = await ConfigurationServer.ReceiveAsync();
// i would send based on what data i received here
int j = 32;
}
}
});
}
I am not receiving data on listen thread. I know that the code on the other side is functional, and sending a directed UDP message to the IP/Port combo.
It can simply be done as
int PORT = 9876;
UdpClient udpClient = new UdpClient();
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, PORT));
var from = new IPEndPoint(0, 0);
var task = Task.Run(() =>
{
while (true)
{
var recvBuffer = udpClient.Receive(ref from);
Console.WriteLine(Encoding.UTF8.GetString(recvBuffer));
}
});
var data = Encoding.UTF8.GetBytes("ABCD");
udpClient.Send(data, data.Length, "255.255.255.255", PORT);
task.Wait();

Receiving and processing continous packets using UDP

This is my current setup (using UDP):
void OnDataReceived(IAsyncResult result)
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
byte[] buffer = socket.EndReceive(result, ref ep);
Packet p = new Packet(Encoding.ASCII.GetString(buffer, 0, buffer.Length));
//process packet
socket.BeginReceive(new AsyncCallback(OnDataReceived), socket);
}
I was wondering what would happen if I immediately call socket.BeginReceive after calling EndReceive and then process the packet to obtain a continous packet flow like this:
void OnDataReceived(IAsyncResult result)
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
byte[] buffer = socket.EndReceive(result, ref ep);
socket.BeginReceive(new AsyncCallback(OnDataReceived), socket);
Packet p = new Packet(Encoding.ASCII.GetString(buffer, 0, buffer.Length));
//process packets
}
If a packet is received as soon as I call BeginReceive, would this conflict with the current packet processing somehow?
Also if this would not conflict would changing to TCP make this disfunctional?
Looks like you are creating some sort of recursive handler there. I am unsure how that will work, probably not in a good way. I usually go for a separate reader thread that listens to incoming data and passes it on to an event. This has served me well in the past. I have not looked into using async for this though.
Here is some example code on how to use a separate thread to handle incoming UDP data. It is not complete but should give you an idea of how to set it up.
private Thread _udpReadThread;
private volatile bool _terminateThread;
public event DataEventHandler OnDataReceived;
public delegate void DataEventHandler(object sender, DataEventArgs e);
private void CreateUdpReadThread()
{
_udpReadThread = new Thread(UdpReadThread) { Name = "UDP Read thread" };
_udpReadThread.Start(new IPEndPoint(IPAddress.Any, 1234));
}
private void UdpReadThread(object endPoint)
{
var myEndPoint = (EndPoint)endPoint;
var udpListener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
// Important to specify a timeout value, otherwise the socket ReceiveFrom()
// will block indefinitely if no packets are received and the thread will never terminate
udpListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100);
udpListener.Bind(myEndPoint);
try
{
while (!_terminateThread)
{
try
{
var buffer = new byte[1024];
var size = udpListener.ReceiveFrom(buffer, ref myEndPoint);
Array.Resize(ref buffer, size);
// Let any consumer(s) handle the data via an event
FireOnDataReceived(((IPEndPoint)(myEndPoint)).Address, buffer);
}
catch (SocketException socketException)
{
// Handle socket errors
}
}
}
finally
{
// Close Socket
udpListener.Shutdown(SocketShutdown.Both);
udpListener.Close();
}
}
public class DataEventArgs : EventArgs
{
public byte[] Data { get; private set; }
public IPAddress IpAddress { get; private set; }
public DataEventArgs(IPAddress ipaddress, byte[] data)
{
IpAddress = ipaddress;
Data = data;
}
}

Categories

Resources