原因分析:
1>Socket缓冲区过小;
2>接收的数据没有保存的临时缓冲区,数据处理造成接收等待;
3>发送的数据包过大超过了UDP包大小限制;
最好不要超过512个字节,因为游戏系统的实现不支持太大的udp包。具体可以看tcp/ip 详解卷1的udp一节。
4>发送方和接收方统一编码,确保中文正常;
5>没有数据接收时进行适当的等待,以免线程CUP占用过高;
示例如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using VanvinfoSource.AddressManager;
using VanvinfoSource;
using VanvinfoSource.LogManager;
namespace VVNetWorking.Netwoking.UDP
{
public class UDPSocketManager : AbstractSocket
{
private UdpClient _listener = null;
private Thread _listenReceiveThread = null;
/// <summary>
/// 启动监听和消息接收
/// </summary>
/// <param name="localhostListenAddress"></param>
public override void Start(AddressInfo localhostListenAddress)
{
base.InitSocket(localhostListenAddress);
try
{
_listener = new UdpClient(localhostListenAddress._Port);
const long IOC_IN = 0x80000000;
const long IOC_VENDOR = 0x18000000;
const long SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
byte[] optionInValue = { Convert.ToByte(false) };
byte[] optionOutValue = new byte[4];
_listener.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET, optionInValue, optionOutValue);
//设置接收缓冲区的容量
_listener.Client.ReceiveBufferSize = 1024 * 1024 * 10;
//启动消息接收线程
_listenReceiveThread = new Thread(delegate() { Receive(); });
_listenReceiveThread.IsBackground = true;
_listenReceiveThread.Start();
_isStartSocketSucess = true;
}
catch (Exception ex)
{
_isStartSocketSucess = false;
VVLogsManager._VVLogsManager.AddLog("启动UDP监听失败," + "IP:" + localhostListenAddress._IpAddress + ":" + localhostListenAddress._Port + ",错误原因:" + ex.Message);
}
}
/// <summary>
/// 消息的发送
/// </summary>
/// <param name="messageModel"></param>
protected override void SendData(MessageModel messageModel)
{
UdpClient uDPSocket = new UdpClient();
try
{
if (!_isStartSocketSucess)
{
VVLogsManager._VVLogsManager.AddLog("启动UDP监听失败,不能发送数据!");
return;
}
messageModel.PreSendingLoad();
byte[] outbytes = Encoding.UTF8.GetBytes(messageModel._Message);
uDPSocket.Connect(messageModel._ToAddress._IpAddress, messageModel._ToAddress._Port);
uDPSocket.Send(outbytes, outbytes.Length);
}
catch (Exception ex)
{
VVLogsManager._VVLogsManager.AddLog("UDP发送失败:" + ex.Message);
}
finally
{
uDPSocket.Client.Dispose();
uDPSocket.Close();
uDPSocket = null;
}
}
private bool _isStopReceive = false;
/// <summary>
/// 消息的接收
/// </summary>
protected override void Receive()
{
IPEndPoint groupEP = null;
byte[] buffer = null;
while (!_isStopReceive)
{
try
{
if (_listener.Available <= 0 || _listener.Client == null)
{
Thread.Sleep(2);
continue;
}
else
{
buffer = _listener.Receive(ref groupEP);
AddMessage(buffer);
}
}
catch (Exception ex)
{
Console.WriteLine("UDP监听异常,"+ex.Message);
}
}
}
/// <summary>
/// 资源释放
/// </summary>
public override void Dispose()
{
base.Dispose();
string message = "";
try
{
_isStopReceive = true;
_listenReceiveThread.Abort();
_listenReceiveThread.Join();
_listener.Close();
message = "停止UDP监听成功,停止监听线程!";
}
catch (Exception ex)
{
VVLogsManager._VVLogsManager.AddLog("关闭监听(CloseSocket)," + ex.Message + ":" + message);
}
}
}
}