我要实现的功能是:一个客户端程序直接服务器建立100-1000个连接,而不是开100-1000个客户端,每个客户端建立一个连接。采用异步编程,然后发送的数据包可以灵活增加和减少。(每个连接发送的数据包相同)实现的界面图如下:1.在点击“发送”按钮后,则开始发起创建100-1000个连接请求。
代码如下:#region 开始准备发送数据包
        /// <summary>
        /// 开始准备发送数据包
        /// 1.禁用相关按钮与容器
        /// 2.判断是否开启了连接,如果连接已开启,则继续操作
        /// 3.是否选择了要发送的数据包,如果没有,则不发送数据包并提示选择数据包
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            #region 禁用按钮与容器
            btnSend.Enabled = false;
            clBoxPacket.Enabled = false;
            clBoxChild.Enabled = false;
            #endregion            TcpClient tcp;
            if (isConnected)
            {
                if (hashTable.Count > 0)
                {
                    txtLog.Text += "(" + DateTime.Now.ToString() + ")开始发送数据包:";                    #region 获取要发送的数据包
                    foreach (DictionaryEntry entry in hashTable)
                    {
                        txtLog.Text += entry.Value.ToString().Split(',')[3] + ",";
                        sPacket += entry.Value + "|";
                    }
                    txtLog.Text = txtLog.Text.Substring(0, txtLog.Text.Length - 1) + "\r\n";
                    #endregion
                }
                else
                {
                    MessageBox.Show("请选择要发送的数据包");
                    return;
                }                #region 创建多个线程 并启动创建连接
                for (int i = 0; i <= sckNum / 30; i++)
                {
                    Thread thread = new Thread(new ParameterizedThreadStart(CreateTcp));
                    thread.Start(i);
                }
                #endregion            }
        }
        #endregion        #region 创建连接并开始连接服务器
        /// <summary>
        /// 
        /// </summary>
        /// <param name="i"></param>
        private void CreateTcp(object i)
        {
            int sNum = sckNum - 30 * Convert.ToInt32(i);
            TcpClient tcp;
            if (sNum >= 30)
            {
                for (int j = 0; j < 30; j++)
                {
                    tcp = new TcpClient();
                    tcp.ConnectedServer += new NetEvent(ClientConn);
                    tcp.SendDatagram += new NetEvent(SendData);
                    tcp.ReceivedDatagram += new NetEvent(RecvData);
                    tcp.Connect(Config.ServerIp, Config.ServerPort);
                    Thread.Sleep(sckNum);
                }
            }
            else
            {
                for (int j = 0; j < sNum; j++)
                {
                    tcp = new TcpClient();
                    tcp.ConnectedServer += new NetEvent(ClientConn);
                    tcp.SendDatagram += new NetEvent(SendData);
                    tcp.ReceivedDatagram += new NetEvent(RecvData);
                    tcp.Connect(Config.ServerIp, Config.ServerPort);
                    Thread.Sleep(sckNum);
                }
            }
        }
        #endregion2.在连接与服务器成功建立连接后,触发相应事件,通知客户端,客户端在接收到事件后,进行以下操作处理
  a.记录连接成功日志
  b.记录连接列表
  c.分析数据包队列,并开始发送第一个数据包
  代码如下:///日志信息记录
            string strLog = "(Socket" + e.Client.ClientSocket.Handle.ToString() + ")建立连接成功\r\n";            lock (this)
            {
                File.AppendAllText(logPath + e.Client.ClientSocket.Handle.ToString() + ".log", strLog);
            }            TcpClient tcpCli = (TcpClient)sender;            ///设置Socket连接需要发送的数据包集合
            tcpCli.Packet = sPacket;            #region 记录Socket列表
            SckItems<int, string> sckItem = new SckItems<int, string>();
            sckItem.Value = e.Client.ClientSocket.Handle.ToInt32();
            sckItem.Text = "Socket" + e.Client.ClientSocket.Handle.ToString();
            if (!lbSckList.Items.Contains(sckItem))
            {
                lbSckList.Items.Add(sckItem);
            }
            #endregion            ///返回数据包集合中的第一个数据包和其余数据包
            ///result[0]为第一个数据包
            ///result[1]为其余数据包集合
            string[] result = Packet.SplitPacket(tcpCli.Packet);
            ///设置数据包集合
            tcpCli.Packet = result[1];
            ///说明信息
            string msg = string.Empty;            #region 发送数据包
            byte[] packetByte;
            string[] itemArray = result[0].Split(',');
            ushort parentType = ushort.Parse(itemArray[0]);
            ushort childType = ushort.Parse(itemArray[1]);
            int childID = int.Parse(itemArray[2]);
            packetByte = Packet.GetPacket(parentType, childType, childID, ref msg);
            ///包说明信息
            msg = itemArray[3] + "|" + msg;
            ///发送数据包
            tcpCli.Send(packetByte, msg);
            #endregion3.服务端接收到发送的数据包后,会进行处理,然后返回一个数据包,当客户端接收到返回数据包时,触发处理事件,进行如下操作:
  a.分析数据包信息并记录日志
  b.分析数据包队列是否发送完毕,如果没有发送完毕,继续发送下一个数据包,否则,关闭连接。
  代码如下:#region 记录日志信息
            string[] msg = GetRecvPacket(e.Client.Datagram).Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            string strLog = "(Socket" + e.Client.ClientSocket.Handle.ToString() + ")接收到“" + msg[0] + "”反馈数据包,反馈信息:" + msg[1];
            strLog = strLog.Substring(0, strLog.Length - 1) + "\r\n";            lock (this)
            {
                File.AppendAllText(logPath + e.Client.ClientSocket.Handle.ToString() + ".log", strLog);
            }
            #endregion            TcpClient tcpCli = (TcpClient)sender;            #region 如果数据包尚未发送完毕,继续发送
            if (tcpCli.Packet != null)
            {
                string[] result = Packet.SplitPacket(tcpCli.Packet);
                ///设置数据包集合
                tcpCli.Packet = result[1];
                ///说明信息
                string infor = string.Empty;                #region 发送数据包
                byte[] packetByte;
                string[] itemArray = result[0].Split(',');
                ushort parentType = ushort.Parse(itemArray[0]);
                ushort childType = ushort.Parse(itemArray[1]);
                int childID = int.Parse(itemArray[2]);
                packetByte = Packet.GetPacket(parentType, childType, childID, ref infor);
                infor = itemArray[3] + "|" + infor;
                tcpCli.Send(packetByte, infor);
                #endregion
            }
            else
            {
                #region 当前连接数据包已全部发送完毕
                lock (this)
                {
                    ///记录已发送数据包
                    sendPacketNum++;
                    ///显示已发送数据包
                    lblSendNum.Text = "已经发送数据包的数量:" + sendPacketNum.ToString();
                    ///设置进度条
                    progressBar1.Value = (sendPacketNum * 100) / sckNum;
                }                lock (this)
                {
                    ///添加日志信息
                    File.AppendAllText(logPath + e.Client.ClientSocket.Handle.ToString() + ".log", "(Socket" + e.Client.ClientSocket.Handle.ToString() + ")断开连接成功\r\n\r\n");
                }
                ///关闭连接等待重用
                tcpCli.Close();
                #endregion
            }
            #endregion主要实现思路都在上面了,由于涉及到灵活增加和减少要发送的数据包,所以所有数据包信息都存储在数据库中,统一从数据库中读取数据包信息然后拼接。这属于共享数据,因此使用了lock锁,会对性能有影响,但是我不知道如何处理比较好?请各位高手,专家多多指点。