想学学C#里面的同步socket和异步socket,于是下了个例子,虽然有bug不过改改勉强可以用了,可是发现客户端多于一个就会报错
ex.Message = "The IAsyncResult object was not returned from the corresponding asynchronous method on this class.\r\nParameter name: asyncResult"
服务端是异步的,代码如下using System;
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.Sockets;
using System.Net;namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private delegate void threaddelegate();
        byte[] RecvData = new byte[65535];
        Socket serverSocket;
        List <Socket> clientsocketlist=new List<Socket>();
        public Form1()
        {
            InitializeComponent();
        }        private void button1_Click(object sender, EventArgs e)
        {
            int connectcount = 100;
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Any,int.Parse(textBox1.Text));
            serverSocket.Bind(iep);
            this.RecieveMsg.AppendText("开始监听.........\n");
            serverSocket.Listen(connectcount);
            serverSocket.BeginAccept(new AsyncCallback(AcceptConn), serverSocket);
        }        void AcceptConn(IAsyncResult iar)
        {
            try
            {
                Socket listener = (Socket)iar.AsyncState;
                Socket client = listener.EndAccept(iar);
                this.clientsocketlist.Add(client);
                IPAddress ip = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address;                threaddelegate settext = delegate()
                {
                 lock (this.RecieveMsg)
                  {
                  this.RecieveMsg.AppendText("服务器已连接" + ip.ToString() + "当前连接数"+this.clientsocketlist.Count.ToString());
                  }
                };
                this.RecieveMsg.Invoke(settext);                //开始接受来自该客户端的数据
                client.BeginReceive(RecvData, 0, RecvData.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
                //继续接受其他客户端的连接
                listener.BeginAccept(new AsyncCallback(AcceptConn), client);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
        }
        
        void ReceiveData(IAsyncResult iar)
        {
            string strRecv;
            Socket client = (Socket)iar.AsyncState;
            int recv = client.EndReceive(iar);
            if (recv == 0)
            {
                this.clientsocketlist.Remove(client);
                client.Close();
            }
            else
            {
                threaddelegate settext = delegate()
                {
                    lock (this.RecieveMsg)
                    {
                        string msgs = Encoding.Unicode.GetString(RecvData, 0, recv);
                        this.RecieveMsg.AppendText(msgs);
                    }
                };
                this.RecieveMsg.Invoke(settext);
                
                //将接收到的数据再发送给客户端
                 client.BeginSend(RecvData, 0, recv, SocketFlags.None, new AsyncCallback(SendData), client);
            }
            //继续接收来自来客户端的数据
            client.BeginReceive(RecvData, 0, RecvData.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
        }
        
        void SendData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            int sent = client.EndSend(iar);
        }        private void button3_Click(object sender, EventArgs e)
        {
            foreach (Socket clients in this.clientsocketlist)
            {
                byte[] sendmsg = Encoding.Unicode.GetBytes(this.textBox2.Text+"\n");
                clients.BeginSend(sendmsg, 0, sendmsg.Length, SocketFlags.None, new AsyncCallback(SendData), clients);
            }
        }
    }
}有谁能帮忙看看哪里出的问题么?或者能给我一个较好的异步服务端代码么?

解决方案 »

  1.   

    错误~
    ex.Message = "The IAsyncResult object was not returned from the corresponding asynchronous method on this class.\r\nParameter name: asyncResult"
    位置在AcceptConn这个函数里面的
         Socket client = listener.EndAccept(iar);
      

  2.   


    如果你是在xp上测试的,那么试一试放到windows7上或者某一版windows server,或者找个软件把你的xp连接数改为1000.
      

  3.   

    我的系统是win7 64位,连接数1000依旧报错,实际上只要开两个客户端就会报错了,客户端是同步的,上网查了下,貌似应该和客户端没什么关系,另外奇怪的是我用的同步服务端就没有这个问题,运行正常,可以起多个客户端,也可以正常传输字符串,我又下了一些例子代码,但是找不出我程序中为什么会出问题
      

  4.   

    问题肯定是出在你在一个Form实例的范围内实例化一个serverSocket。具体的代码可能还要自己测试。说实在的,我从来没有想过在Form去启动过什么Socket服务。
      

  5.   

    监听就没必要异步了,while都不加sleep的循环就可以了,建立连接就可有异步了..有的时候我还是习惯开线程去处理,因为我觉得思路清晰点,这个异步同步的,多了就乱了,尤其还是判断数据是否传完,是否异常等..
      

  6.   


    从错误信息上判断,AcceptConn方法出现了错误,再从楼主描述的错误情况来看
    判断 
    threaddelegate settext = delegate()
      {
      lock (this.RecieveMsg)
      {
      this.RecieveMsg.AppendText("服务器已连接" + ip.ToString() + "当前连接数"+this.clientsocketlist.Count.ToString());
      }
      };
    肯定是这段出现了错误,你已经把委托要做的事情放到了异步方法内了;这里你应该要好好理解一下,委托的作用应该将方法独立开来,void SetText() 
    {
       .....
    }代码改成
      Invoke(new threaddelegate(ISetText));
      

  7.   

    答11L 其实那段代码是网上下的,只是为了简单理解下C#里的异步socket,可惜就是bug太多了,而且对于大量的使用回调函数不是很习惯,以前感觉java和delphi中的socket阻塞模式思路很清晰,不过因为阻塞模式不是万能的,据说异步模式可以节省资源,所以想学习下答12L,那个委托的代码确实是多余了,因为总是出问题,所以我临时加进去想判断下连接是否正确
      

  8.   

    目前错误提示的问题我已经解决了,不过这段代码里的bug太多了,各种崩溃,唉,学习不容易啊
      

  9.   

    最近也在做socket的东西,开了1000个线程,结果客户端意外关闭了,1000个线程还在,郁闷中....
      

  10.   

    呵呵,上面我回复时其实只是看到了你的代码的Connect部分,根本没有耐心往下看。而且你的问题也是出在connect部分,所以也因此懒得往下看。刚刚想起来,看看你的缓冲区怎么声明吧。可是一看吓了我一大跳,连这个RecvData 也是共享的啊?看来你真的被顺序处理的程序给害得不轻啊。这样共享一堆东西,你一旦并行处理就会出现各种诡异的bug了。
      

  11.   

    1那个共享内存问题我发现了,不过网上得来的东西我也不想去奢求太多,能通过就不错了,先理解下,机制了解了再慢慢修改2 昨天的问题是因为代码里面的连接用错了 ,应该是这样
    listener.BeginAccept(new AsyncCallback(AcceptConn), listener);3  另外另外这段代码里还有很多bug,例如没有对客户端非常断开作处理,导致一但有一个客户端关闭,服务端就崩溃了,应该把下面这个做异常判断处理
      client.BeginSend(RecvData, 0, recv, SocketFlags.None, new AsyncCallback(SendData), client);
       }
       //继续接收来自来客户端的数据
       client.BeginReceive(RecvData, 0, RecvData.Length, SocketFlags.None, new AsyncCallback(ReceiveData), 4 代码调试中发现这个判断完全没起作用,不知道在异步模式中是不是用这种方式来判断客户端断开的,继续研究中
      if (recv == 0)
       {
       this.clientsocketlist.Remove(client);
       client.Close();
       }
     
      

  12.   

    推荐你看看C_网络编程.pdf,然后写socket程序,手到擒来
      

  13.   

    我遇到这个情况,是使用Socket.BeginSendFile()造成的,去掉就好了。