日期:2014-05-18  浏览次数:20856 次

多客户端Socket问题,感兴趣就来吧
这一次我做多客户端对服务器相互对话,我的思路是每当有一个客户端连接到服务器的时候,服务器增加一个CheckBox,可是我发现除了第一个客户端连接进来的时候服务器会增加一个CheckBox,后面的客户端连接服务器都增加了CheckBox但是界面上就是不显示(这是为什么,跟Control.Invoke方法有关么)。调试了好久找不到原因,麻烦各位朋友帮忙看看。源码如下:
  TcpListener tcpListener;
  //判断是否已经启动监听
  bool IsBeginListen = false;
  //当前连接数
  int linkCount = 0;
  //客户端连接列表
  List<TcpClient> clientArray;
  public MyServer()
  {
  InitializeComponent();
  }

  /// <summary>
  /// 启动tcp端口监听
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void btnStart_Click(object sender, EventArgs e)
  {
  //如果已经开始监听了,则返回
  if (IsBeginListen)
  {
  return;
  }
  IsBeginListen = true;

  //开始一个线程启动监听
  Thread thread = new Thread(new ThreadStart(StartListen));
  thread.Start();
  }

  /// <summary>
  ///异步启动监听
  /// </summary>
  void StartListen()
  {
  //开始Tcp监听
  IPEndPoint ip = new IPEndPoint(IPAddress.Parse(txtAddress.Text), int.Parse(txtPort.Text));
  tcpListener = new TcpListener(ip);
  tcpListener.Start(10000);
  //初始化clientArray;
  clientArray = new List<TcpClient>(1500);
  lblTip.Invoke(new Action(delegate() { lblTip.Text = "已启动监听"; }));
  // lblTip.Text = "已启动监听";
  while (true)
  {
  //如果监听数达到1200个,则不继续增加监听
  if (linkCount > 1200)
  {
  Thread.Sleep(10000);
  continue;
  }
  //开始异步接收客户端请求
  tcpListener.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpAsync), tcpListener);
  //开始一个监听,则监听数加1
  linkCount++;
  }
  }

  /// <summary>
  /// 异步接受客户端请求后的回调
  /// </summary>
  /// <param name="res"></param>
  void AcceptTcpAsync(IAsyncResult res)
  {
  TcpListener listener = res.AsyncState as TcpListener;
  if (listener != null)
  {
  TcpClient client = listener.EndAcceptTcpClient(res);
  int index = 0;
  //这里一定要同步,以便正确获取当前Tcp连接在列表中的索引
  lock (this)
  {
  clientArray.Add(client);
  index = clientArray.Count - 1;
  //每接收一个连接,则在panelClient里增加一个复选框,问题就出来这里,我调试发现第二个客户端连接服务器的时候,panelClient明明增加了一个CheckBox,可是界面上就是不显示,但是我新增加的客户端发送消息服务器都能收到,这是为什么?
  panelClient.Invoke(new Action<int>((arg) => { CheckBox ck = new CheckBox(); ck.Name = "ck" + arg.ToString(); ck.Text = "客户端:" + arg.ToString(); panelClient.Controls.Add(ck); ck.Select(); }), index);  
  }

  //用指定的Socket缓冲区大小初始化接收客户端数据的字节数组,默认为8KB
  byte[] re