-
-
Save darkguy2008/413a6fea3a5b4e67e5e0d96f750088a9 to your computer and use it in GitHub Desktop.
using System; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
namespace UDP | |
{ | |
public class UDPSocket | |
{ | |
private Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | |
private const int bufSize = 8 * 1024; | |
private State state = new State(); | |
private EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0); | |
private AsyncCallback recv = null; | |
public class State | |
{ | |
public byte[] buffer = new byte[bufSize]; | |
} | |
public void Server(string address, int port) | |
{ | |
_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true); | |
_socket.Bind(new IPEndPoint(IPAddress.Parse(address), port)); | |
Receive(); | |
} | |
public void Client(string address, int port) | |
{ | |
_socket.Connect(IPAddress.Parse(address), port); | |
Receive(); | |
} | |
public void Send(string text) | |
{ | |
byte[] data = Encoding.ASCII.GetBytes(text); | |
_socket.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) => | |
{ | |
State so = (State)ar.AsyncState; | |
int bytes = _socket.EndSend(ar); | |
Console.WriteLine("SEND: {0}, {1}", bytes, text); | |
}, state); | |
} | |
private void Receive() | |
{ | |
_socket.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) => | |
{ | |
State so = (State)ar.AsyncState; | |
int bytes = _socket.EndReceiveFrom(ar, ref epFrom); | |
_socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so); | |
Console.WriteLine("RECV: {0}: {1}, {2}", epFrom.ToString(), bytes, Encoding.ASCII.GetString(so.buffer, 0, bytes)); | |
}, state); | |
} | |
} | |
} |
using System; | |
namespace UDP | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
UDPSocket s = new UDPSocket(); | |
s.Server("127.0.0.1", 27000); | |
UDPSocket c = new UDPSocket(); | |
c.Client("127.0.0.1", 27000); | |
c.Send("TEST!"); | |
Console.ReadKey(); | |
} | |
} | |
} |
Perfect, thank you!
Awesome!! Thank you!!
Not bad, smart concept
I'm sorry if this is a really dumb question, I'm relatively new to writing C# from scratch (I normally just edit preexisting code to fix issues and patch functionality), but would my receive data handler have to go inside of this class's Receive method? Or is there a way for me to have Receive return a new packet if it finds one or return an empty byte array if it doesn't? Due to my functional programming background I'd rather do the latter
@JoshuaDoes : If you want to acsess the received data from outside i would suggest using an event callback (thats what i did, @op thanks for the code btw). Therefore you need to define the delegate public delegate void UdpOnReceived(byte[] data, int bytesRead);
should add the public field public event UdpOnReceived OnReceived;
to the UDPSocket-Class and add OnReceived?.Invoke(state.buffer, bytes);
to the Receive function.
Now you would be able to attach a listener from outside to the Class like var socket = new UDPSocket(); //...blablabla... socket.OnReceived += MyReactionFunction;
. Then you could play with your data inside of those MyReactionFunctions.
@SchneiderJonathan great idea! And thanks @darkguy2008 and @louis-e for the code and edits!
Thank you for the event callback idea @SchneiderJonathan, much appreciated!
Is there a way to send from server back to client?
Is there a way to send from server back to client?
Declare a client on the servers code and connect him to the loopback ip address.
Is there a way to send from server back to client?
Declare a client on the servers code and connect him to the loopback ip address.
Can you give an example ^^
You basically just have to declare a new client (in addition to the server and the already existing clients):
UDPSocket c = new UDPSocket();
Then you connect your just new declared client to your server (I assumed that the server runs on localhost and port 27000)
c.Client("127.0.0.1", 27000);
After that you can send your message over this new declared client to the other clients.
c.Send("TEST!");
Important Note: Using UDP over Internet
I used this code as part of a multiplayer game server component. It worked fine once I added a SendTo() method for the server sending to clients. However, once I moved from testing on LAN to over the Internet I had issues. I had a static IP for my router and set up port forwarding. Was receiving UDP packets from clients, but any responses back to clients were disappearing. However, I removed the line:
_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
And it started working over Internet too.
This works for me locally but when I send to a remote host I don't receive anything even though Wireshark shows the data coming back correctly from the remote host.
UDPSocket s = new UDPSocket();
s.Server("127.0.0.1", 2000);//binds to the local endpoint
UDPSocket c = new UDPSocket();
c.Client("192.168.26.186", 1999);//connects to the remote host
c.Send("0500020a04");
Any ideas why?
Assuming your remote host is in your local network; You have to use your local ip address (192.168.x.x) instead of the localhost 127.0.0.1 in your server declaration line (s.Server("127.0.0.1", 2000);
). In addition to that you also have to use the same port for both server and client (e.g. 2000) 👍
Assuming your remote host is in your local network; You have to use your local ip address (192.168.x.x) instead of the localhost 127.0.0.1 in your server declaration line (
s.Server("127.0.0.1", 2000);
). In addition to that you also have to use the same port for both server and client (e.g. 2000) 👍
Thanks for responding louis-e.
The remote host is in the local network so I am working with local Server 192.168.30.200 and remote Client 192.168.26.186. The client is a piece of industrial hardware that only receives on port 1999 and sends to port 2000 so I can't use the same port number. I proved correct communication using Packet Sender.
Perhaps I am going about this wrong. I am sending UDP successfully. As you can see from the Wireshark screen shot, the device is responding correctly to port 2000 of the local Server. I just am not receiving the data.
What is a better approach to receive the UDP from port 2000?
Okay, I understand. Did you try to use s.Server("192.168.30.200", 2000);
for declaring the server?
That was it. I thought I has tried that but I guess not. It works now. Thanks so much!
Thanks a lot! , It works fluently in my project
Thank you. Can you do it for TCP?
s.Server("127.0.0.1", 27000);
It's a local IP or remote? What if I don't know a remote IP? I want to receive from any socket.
Thanks! I was looking for a good example of UDP and this is a nice starting point.
Is it suppose to work easily ? I'm new with that client/servers code.
How to send a full file or image that sized 0.6mb or 600kb
good job