我最近有玩Socket 的多线程的问题
 但我的程序逻辑有些问题,我的Server端可以接受多个Client端的连接,并且都能接受他们所发送过来的数据,但只要其中一个Client端断开后,服务器端就接受不了其他Client端发送过来的数据,我知道我的逻辑有问题(后面是我的Server端的部分代码),但我不知道怎么写?请各位大侠指教!谢谢
 然后我的Server端需要要向指定的Client端发送数据,这么我怎么才能做的到?(向指定的Client发送指定信息), 请大侠们指教一下,最好有代码,谢谢!以下是我Server端的部分代码:  //开启线程
        public void StartThread()
        {           // ClientNumber++;
            ServerThread = new Thread(new ThreadStart(RecieveAccept));//将接受客户端连接的方法委托给线程            ServerThread.Start();            CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用            this.SetText("服务于" + DateTime.Now.ToString() + "开始运行");
        }   //接受客户端连接的方法和接收数据
        private void RecieveAccept()
        {
                        while(true)
            {
                //ClientNumber++;               ServerSocket.Listen(10);//开始监听,并且挂起数为10                 ClientSocket[ClientNumber] = ServerSocket.Accept();                this.StartThread();
                ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
                this.SetText(ClientSocket[ClientNumber].RemoteEndPoint.ToString());                //this.StartReceiveMsgThread();                while (m == 1)
                {
                    try
                    {
                        i = ClientSocket[ClientNumber].Receive(msgbuffer);
                        //ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
                    }
                    catch (Exception)
                    {                        MessageBox.Show("有一客户端断开", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        //return;
                        break;
                    }
                    msg = Encoding.Unicode.GetString(msgbuffer, 0, msgbuffer.Length);
                    this.SetText(msg);                    System.Array.Clear(msgbuffer, 0, msgbuffer.Length);                    if (msg.Trim() == "stop")
                    {
                        m = 0;
                    }                }
                //this.SetText(msgbuffer.ToString());
              ClientNumber++;            }
        
        }

解决方案 »

  1.   

    发送数据到指定的IP指定的端口没问题,但我其中一个Client端断开后Server 端就接受不到了其他Client端的数据了,郁闷中,还有Server怎么向指定的Client发送消息?请各位高手指教
      

  2.   

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.IO;namespace AsyncTcpServer
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                setComboBoxCallback = new SetComboBoxCallback(SetComboBox);
                setListBoxCallback = new SetListBoxCallback(SetListBox);
                setRichTextBoxCallback = new SetRichTextBoxCallback(setRichText);
                removeComboBoxItemsCallback = new RemoveComboBoxItemsCallback(RemoveComboBoxItems);
            }
            private bool isExit = false;
            System.Collections.ArrayList clientList = new System.Collections.ArrayList();//保存连接所有的客服端
            TcpListener listener;//监听客服端连接
            private delegate void SetListBoxCallback(string str);
            private SetListBoxCallback setListBoxCallback;
            private delegate void SetRichTextBoxCallback(string str);
            private SetRichTextBoxCallback setRichTextBoxCallback;
            private delegate void SetComboBoxCallback(string str);
            private SetComboBoxCallback setComboBoxCallback;
            private delegate void RemoveComboBoxItemsCallback(ReadWriteObject readWriteObject);
            private RemoveComboBoxItemsCallback removeComboBoxItemsCallback;        private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);//用于线程同步,初始为非终止状态,使用手动设置方式
            
            private void RemoveComboBoxItems(ReadWriteObject readWriteObject)
            {
                int index = clientList.IndexOf(readWriteObject);
                comboBox1.Items.RemoveAt(index);
            }        private void SetListBox(string str)
            {
                listBox1.Items.Add(str);
                listBox1.SelectedIndex = listBox1.Items.Count - 1;
                listBox1.ClearSelected();
            }        private void setRichText(string str)
            {
                receive_text.AppendText(str);
            }        private void SetComboBox(object obj)
            {
                comboBox1.Items.Add(obj);
            }        private void AcceptConnect()
            {
                IPAddress[] ip = Dns.GetHostAddresses(Dns.GetHostName());//获取本机IP地址
                listener = new TcpListener(ip[0], 51888);//创建监听
                listener.Start();//启动监听
                while(isExit==false)//循环监听客服端发过来的请求
                {
                    try
                    {
                        allDone.Reset();//将事件设置为非终止状态,不让操作系统发出信号
                        AsyncCallback callback = new AsyncCallback(AcceptTcpClient);//引用在异步操作完成时调用的方法
                        listBox1.Invoke(setListBoxCallback, "开始等待客户连接");
                        listener.BeginAcceptTcpClient(callback, listener);//开始一个异步操作接收传来的连接尝试
                        allDone.WaitOne();//阻塞当前线程,直到收到客服端的连接信号
                    }
                    catch (Exception ex)
                    {
                        listBox1.Invoke(setListBoxCallback, ex.Message);
                        break; 
                    }
                }
            }        private void AcceptTcpClient(IAsyncResult ar)//ar 异步操作状态
            {                                            //是由 listener.BeginAcceptTcpClient(callback, listener)传递过来的
                try
                {
                    allDone.Set();//将事件状态设置为终止,让等待的一个或者多个线程继续
                    TcpListener myListener = (TcpListener)ar.AsyncState;
                    TcpClient client = myListener.EndAcceptTcpClient(ar);//异步接收传入的连接,并创建新的Tcplient对象处理远程主机通信
                    listBox1.Invoke(setListBoxCallback, "已接受客服连接:" + client.Client.RemoteEndPoint);
                    comboBox1.Invoke(setComboBoxCallback, client.Client.RemoteEndPoint.ToString());
                    ReadWriteObject readWriteObject = new ReadWriteObject(client);
                    clientList.Add(readWriteObject);
                    SendString(readWriteObject, "服务器已经接受连接,请通话!");
                    //开始异步读取
                    readWriteObject.netStream.BeginRead(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
                }
                catch(Exception ex)
                {
                    listBox1.Invoke(setListBoxCallback, ex.Message);
                    return;
                }
            }        private void ReadCallback(IAsyncResult ar)
            {
                try
                {
                    ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
                    int count = readWriteObject.netStream.EndRead(ar);
                    receive_text.Invoke(setRichTextBoxCallback, string.Format("[来自{0}]{1}", readWriteObject.client.Client.RemoteEndPoint, System.Text.Encoding.UTF8.GetString(readWriteObject.readBytes, 0, count)));
                    if(isExit==false)
                    {
                        readWriteObject.InitReadArray();
                        readWriteObject.netStream.BeginRead(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
                    }
                }
                catch(Exception ex)
                {
                    listBox1.Invoke(setListBoxCallback, ex.Message);
                }
            }
            private void SendString(ReadWriteObject readWriteObject,string str)
            {
                try
                {
                    readWriteObject.writeBytes = System.Text.Encoding.UTF8.GetBytes(str + "\r\n");
                    //开始向流异步写入数据
                    readWriteObject.netStream.BeginWrite(readWriteObject.writeBytes, 0, readWriteObject.writeBytes.Length, new AsyncCallback(SendCallback), readWriteObject);
                    readWriteObject.netStream.Flush();//刷新流中的数据
                    listBox1.Invoke(setListBoxCallback, string.Format("向{0}发送:{1}", readWriteObject.client.Client.RemoteEndPoint, str));
                }
                catch(Exception ex)
                {
                    listBox1.Invoke(setListBoxCallback, ex.Message);
                }
            }        private void SendCallback(IAsyncResult ar)
            {
                ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
                try
                {
                    readWriteObject.netStream.EndWrite(ar);//结束异步流的写入
                }
                catch(Exception ex)
                {
                    listBox1.Invoke(setListBoxCallback, ex.Message);
                    comboBox1.Invoke(removeComboBoxItemsCallback, readWriteObject);
                }
            }
            private void start_btn_Click(object sender, EventArgs e)
            {
                ThreadStart ts = new ThreadStart(AcceptConnect);//监听客服端的请求
                Thread myThread = new Thread(ts);
                myThread.Start();
                start_btn.Enabled = false;
                stop_btn.Enabled = true;
            }        private void stop_btn_Click(object sender, EventArgs e)
            {
                isExit = true;
                allDone.Set();
                start_btn.Enabled = true;
                stop_btn.Enabled = false;
            }        private void send_btn_Click(object sender, EventArgs e)
            {
                int index = comboBox1.SelectedIndex;
                if(index==-1)
                {
                    MessageBox.Show("请先选择接受方,然后在发送");
                }
                else
                {
                    ReadWriteObject obj = (ReadWriteObject)clientList[index];
                    SendString(obj, send_text.Text);
                    send_text.Clear();
                }
            }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                stop_btn_Click(null, null);
            }
           
        }
    }
      

  3.   

    看看这个例子,封装地比较好:
    源代码和实现说明:
    http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx效果图:
      

  4.   

    要开一个Listen线程。
    一个Receive线程。
    你少了一个Listen线程。
      

  5.   

    从下面的代码开始到最后,放到一个单独的线程处理,,
    ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new 
    AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
    接收连接请求用一个独立的线程处理,针对每一个连接请求创建新工作线程,
    监听请求如下面的模式: private void RecieveAccept()
     {
      while(true)
      {
      //ClientNumber++;  ServerSocket.Listen(10);//开始监听,并且挂起数为10    ClientSocket[ClientNumber] = ServerSocket.Accept();  this.StartThread();//这里同时将套接字以参数方式传递给工作线程
    ......
    }
      

  6.   

    看看msdn上socket的经典例子,同步异步都有:
    http://msdn.microsoft.com/zh-cn/library/w89fhyex.aspx
      

  7.   


    怎么样把Socket传给线程啊?
      

  8.   


    你前面已经BEGINReceive了,那么ENDReceive的逻辑就应该在BEGINRECEIVE的异步回调函数里写啊。
    而你后面又跟了个RECEIVE这个是阻塞的啊。没有数据来,就一直阻塞到的。你后面的连接怎么进得来呢?