98 lines
2.9 KiB
C#
98 lines
2.9 KiB
C#
namespace SimpleUdp
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Collections.Concurrent;
|
|
|
|
|
|
internal class State
|
|
{
|
|
internal State(int bufferSize)
|
|
{
|
|
Buffer = new byte[bufferSize];
|
|
}
|
|
|
|
internal byte[] Buffer = null;
|
|
}
|
|
public class UdpEndpoint : IDisposable
|
|
{
|
|
private Socket _Socket = null;
|
|
private int _MaxDatagramSize = 65507;
|
|
private EndPoint _Endpoint = new IPEndPoint(IPAddress.Any, 0);
|
|
private SemaphoreSlim _SendLock = new SemaphoreSlim(1, 1);
|
|
|
|
public UdpEndpoint(string ip, int port)
|
|
{
|
|
var ipAddress = IPAddress.Parse(ip);
|
|
|
|
_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
|
_Socket.Bind(new IPEndPoint(ipAddress, port));
|
|
|
|
State state = new State(_MaxDatagramSize);
|
|
|
|
_Socket.BeginReceiveFrom(state.Buffer, 0, _MaxDatagramSize, SocketFlags.None,
|
|
ref _Endpoint, ReceiveCallback, state);
|
|
}
|
|
|
|
private void ReceiveCallback(IAsyncResult ar)
|
|
{
|
|
try
|
|
{
|
|
State so = (State)ar.AsyncState;
|
|
int bytes = _Socket.EndReceiveFrom(ar, ref _Endpoint);
|
|
|
|
if (bytes > 0 && bytes < so.Buffer.Length)
|
|
{
|
|
byte[] buffer = new byte[bytes];
|
|
Buffer.BlockCopy(so.Buffer, 0, buffer, 0, bytes);
|
|
|
|
// 直接使用接收到的 EndPoint 进行回复
|
|
string senderIpPort = _Endpoint.ToString();
|
|
string[] parts = senderIpPort.Split(':');
|
|
|
|
if (parts.Length == 2)
|
|
{
|
|
SendInternal(parts[0], int.Parse(parts[1]), new byte[] { 0x01, 0x01 });
|
|
}
|
|
}
|
|
|
|
// 继续接收
|
|
_Socket.BeginReceiveFrom(so.Buffer, 0, _MaxDatagramSize, SocketFlags.None,
|
|
ref _Endpoint, ReceiveCallback, so);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 处理异常
|
|
}
|
|
}
|
|
|
|
private void SendInternal(string ip, int port, byte[] data)
|
|
{
|
|
_SendLock.Wait();
|
|
|
|
try
|
|
{
|
|
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ip), port);
|
|
// 使用同一个 Socket 发送回复
|
|
_Socket.SendTo(data, remoteEP);
|
|
}
|
|
finally
|
|
{
|
|
_SendLock.Release();
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_Socket.Close();
|
|
_Socket.Dispose();
|
|
}
|
|
}
|
|
}
|