首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

C#Socket异步通信在处置批量并发时有时出现数据重叠

2013-12-13 
C#Socket异步通信在处理批量并发时有时出现数据重叠代码如下:当并发数量较大时,会出现数据冲突,求改进方案

C#Socket异步通信在处理批量并发时有时出现数据重叠
代码如下:当并发数量较大时,会出现数据冲突,求改进方案

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Collections.Specialized;
using System.Threading;

namespace SocketServer
{
    public partial class frmMain : Form
    {
        static int count = 0;
        static int recvCount = 0;

        public frmMain()
        {
            InitializeComponent();
        }

        private delegate void ShowMsgHandler(string msg);

        IList<Socket> clientList = new List<Socket>();
        Dictionary<Socket, System.Threading.Timer> clientArray = new Dictionary<Socket, System.Threading.Timer>();

        private void ShowMsg(string msg)
        {
            if (!txtContent.InvokeRequired)
            {
                txtContent.Text = msg + Environment.NewLine + txtContent.Text;
            }
            else
            {
                ShowMsgHandler handler = new ShowMsgHandler(ShowMsg);
                BeginInvoke(handler, new object[] { msg });
            }

        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            IPAddress[] localIPs;
            localIPs = Dns.GetHostAddresses(Dns.GetHostName());
            StringCollection IpCollection = new StringCollection();
            foreach (IPAddress ip in localIPs)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork) //如果为IPv4
                {
                    if (Int32.Parse(txtPort.Text.ToString()) != 0)
                    {
                        TcpListener listener = new TcpListener(ip, Int32.Parse(txtPort.Text.ToString()));
                        listener.Start();
                        listener.BeginAcceptTcpClient(new AsyncCallback(OnAcceptedTcpClient), listener);
                    }
                    else
                    {
                        TcpListener listener = new TcpListener(ip, 6000);
                        listener.Start();
                        listener.BeginAcceptTcpClient(new AsyncCallback(OnAcceptedTcpClient), listener);
                    }


                    
                   
                    txtContent.Text = "Start Listiner...";
                    btnStartServer.Enabled = false;
                    ShowMsg(ip.ToString());
                    break;
                }
            }   
        }

        byte[] buffer = new byte[1024];

        public void TimerCallback(object state)
        {
            
            Socket sock = (Socket)state;
            if (clientArray.Remove(sock))
            {
                ShowMsg("TimerCallback");
            }
            sock.Close(100);
        }

        private void OnAcceptedTcpClient(IAsyncResult ar)
        {
            if (!ar.IsCompleted)
            {
                return;
            }
            TcpListener listener = (TcpListener)ar.AsyncState;
            TcpClient client = listener.EndAcceptTcpClient(ar);
            System.Threading.Timer time = new System.Threading.Timer(TimerCallback, client.Client, 20000, 10000);
            clientArray.Add(client.Client, time);

            ShowMsg("连接成功 ");
            count++;
            listener.BeginAcceptTcpClient(new AsyncCallback(OnAcceptedTcpClient), listener);
            {
                client.Client.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(OnReceivedData), client.Client);
            }
    
        }

        private void OnReceivedData(IAsyncResult ar)
        {
 

            if (!ar.IsCompleted)
            {
                return;
            }
            Socket s = (Socket)ar.AsyncState;
            try
            {
                int size = s.EndReceive(ar);
                if (size > 0)
                {
                    {
                        string str = System.Text.Encoding.Default.GetString(buffer, 0, size);
                        ShowMsg(str);
                    }  

                    recvCount++;


                    clientArray.Remove(s);
                    s.Shutdown(SocketShutdown.Both);
                    s.Close(100);
                }
                else
                {
                    clientArray.Remove(s);
                    s.Close(100);

                    return;
                }
//                 s.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(OnReceivedData), s);
            }
            catch (SocketException )
            {
                clientArray.Remove(s);

                s.Close(100);
            }

        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            byte[] msg = System.Text.Encoding.Unicode.GetBytes(txtMsg.Text.Trim());
            foreach (Socket s in clientList)
            {
                s.BeginSend(msg, 0, msg.Length, SocketFlags.None, new AsyncCallback(OnSendMsg), s);
            }
        }

        private void OnSendMsg(IAsyncResult ar)
        {
            if(!ar.IsCompleted)
            {
                return;
            }
            Socket s = (Socket)ar.AsyncState;
            s.EndSend(ar);
        }

        private void TotleCount_Click(object sender, EventArgs e)
        {
            ShowMsg("连接数:" + count.ToString() +"  收包数:" + recvCount + " 现连接: " + /*clientList.Count*/clientArray.Count);
        }
    }
}


[解决办法]
1.服务端accept一个client后  不能使用同一个buffer接收数据  
2.数据接收返回后,buffer不一定是完整的数据
[解决办法]
如果前后两个连接数据同时到达 写入缓冲区后 就会覆盖  总有一个连接的EndReceive()不会返回 或者返回了 size也为零
你不要以为客户端按顺序先后登录发送数据  它们到达服务器的顺序就是一定是先后顺序的  所以buffer用同一个没事儿  不一定

热点排行