UDP通信数据丢失、乱码的原因分析

原因分析:

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);
            }
        }
    }
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值