Sorry for my poor English.
But I have some questions when I use the UdpClient
in C#:
- In the Task function
ReceiveMessage()
, could I lock theudpClient
for the thread safe? As theudpClient
being locked, couldSendMessage()
run correctly in main thread? - Should I refactor
SendMessage()
in async way to improve the performance? (I plan to send about 30 tiny msg per second) - Did I stop the
udpClient
in the right way?udpClient.ReceiveAsync()
did not provide aCancellationToken
which I usually used to stop a task. Now in my code, when I close theudpClient
, this task can be aborted finally. I don't know is it right or not.
Here is the code:
public class ClientSocket
{
IPEndPoint serverEndPoint;// ServerEP
UdpClient udpClient;// UDPSocket
byte[] msg_buff;//buff
Task receiveTask; //the receive Task
bool isWait2Receiving;//is waiting
Action<byte[]> receiveAction; //after receive callback, must be called in main thread
/// <summary>
/// Create One Client
/// </summary>
public ClientSocket(Action<byte[]> receiveAction, int buffSize = 1024)
{
this.receiveAction = receiveAction;
msg_buff = new byte[buffSize];
}
/// <summary>
/// Init UDP Socket
/// </summary>
public void StartUDP(string hostName, int port)
{
if (isWait2Receiving)
{
return;
}
serverEndPoint = new IPEndPoint(IPAddress.Parse(hostName), port);
udpClient = new UdpClient();
udpClient.Connect(serverEndPoint);
isWait2Receiving = true;
receiveTask = ReceiveMessage();
}
/// <summary>
/// stop UDP Socket
/// </summary>
public void StopUDP()
{
if (!isWait2Receiving)
{
return;
}
udpClient.Close();
udpClient = null;
isWait2Receiving = false;
}
/// <summary>
/// send message call in main thread
/// </summary>
public void SendMessage(UDPHead head, IMessage message)
{
byte[] headData = head.ToByteArray();
byte[] data = message.ToByteArray();
int size = UDPHead.headByteNum + data.Length;
if (size > msg_buff.Length)
{
Debug.LogError("SendMessage prefix size or buff overflow error");
return;
}
headData.CopyTo(msg_buff, 0);
data.CopyTo(msg_buff, UDPHead.headByteNum);
udpClient?.Send(msg_buff, size);
}
/// <summary>
/// Receive Task
/// </summary>
private async Task ReceiveMessage()
{
while (isWait2Receiving)
{
try
{
UdpReceiveResult result = await udpClient?.ReceiveAsync();
//it's a thread safe queue
XXX.Add2OtherThreadWaitUpdateCall(() => receiveAction?.Invoke(result.Buffer));
}
catch (Exception e)
{
XXX.Add2OtherThreadWaitUpdateCall(() => Debug.LogError("ReceiveMessage Error" + e + e.StackTrace));
}
}
}
}