关于c#的Socket异步网络编程问题

小弟正在做一个关于socket,tcp异步的网络系统,服务器上的编程是这样的IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 12343);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(1000);上面是基础,下面是个线程 while (true)
{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}当个有个连接的时候我到AcceptCallback这个回调函数里去设置allDone.set;
一般情况下没有问题,但遇到特殊情况的时候还是问题不少的,比如回调函数AcceptCallback
里不去设置allDone.set,也就是listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
只启动一次,客户端那边也能异步连接上,不报错,但服务器这边除了第一个客户连接会触发回调函数
后面的就不会触发了,说明后面的客户端对于服务器来讲没连接上,但客户端那边确显示连接了,现在我
手动在服务器上allDone.set之后,对于服务器来讲后面的客户端都连接不上了,就是不能执行到回调函
数了,请问现在服务器是卡在哪个地方了。我通过怎么样的方式可以解决这样的问题!
因为客户端有重连机制,如果二个客户端刚在重启,我服务器断开之后也刚重启,二个或三个客户端会被同
一个listener.BeginAccept接收,这样服务器肯定会出问题了 无论我怎么样allDone.set,当客户端连接的
时候 不会到达回调函数那了

这样的写法有点问题:

1)服务器端既然采用了异步方式Accept,就没有必要再启线程

2)估计allDone是一个ManualResetEvent。用ManualResetEvent的目的什么呢?

服务器端采用异步Accept的代码其实很简单,也不需要ManualResetEvent同步

   public class AppTCPServer
    {
        public AppTCPServer(string localIP, int port)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, 
                                                        SocketType.Stream, 
                                                        ProtocolType.Tcp);
            EndPoint localEP = new IPEndPoint(IPAddress.Parse(localIP), port);
            socket.Bind(localEP);
            socket.Listen(100);
            socket.BeginAccept(AcceptAsync, socket);
        }

        private void AcceptAsync(IAsyncResult ar)
        {
            Socket socket = ar.AsyncState as Socket;
            try
            {
                Socket client = socket.EndAccept(ar);
                Console.WriteLine("客户端连接成功!客户端:{0}", client.RemoteEndPoint.ToString());
                if (OnConnected != null)
                {
                    OnConnected(this, new ClientConnectedEventArgs(client));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("AcceptAsync发生异常,异常信息:\n{0}", e.Message);
            }
            finally
            {
                //继续异步Accept
                socket.BeginAccept(AcceptAsync, socket);
            }
        }

        //客户端连接后的事件 OnConnect
        public event EventHandler<ClientConnectedEventArgs> OnConnected;
    }

    /// <summary>
    /// 事件参数:接收客户端连接后的事件参数
    /// </summary>
    public class ClientConnectedEventArgs : EventArgs
    {
        public ClientConnectedEventArgs(Socket clientSocket)
        {
            ClientSocket = clientSocket;
        }
        public Socket ClientSocket { get; private set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            AppTCPServer server = new AppTCPServer("127.0.0.01", 8000);
            server.OnConnected += server_OnConnected;
            Console.WriteLine("按任意键结束程序……");
            Console.ReadKey();
        }

        static void server_OnConnected(object sender, ClientConnectedEventArgs e)
        {
            Socket client = e.ClientSocket;
            string hello = "Hello from AppTCPServer";
            client.Send(Encoding.Default.GetBytes(hello));
        }
    }

 客户端测试程序

   class Program
    {
        static void Main(string[] args)
        {
            //模拟100个客户连接服务器
            for (int i = 0; i < 100; i++)
            {
                Socket socket = ConnectToServer("127.0.0.1", 8000);
                byte[] buffer = new byte[1024];
                int bytesRecevied = socket.Receive(buffer, buffer.Length, SocketFlags.None);
                byte[] messageBytes = new byte[bytesRecevied];
                Array.Copy(buffer, messageBytes, bytesRecevied);
                Console.WriteLine(Encoding.Default.GetString(messageBytes));
                socket.Disconnect(false);
                socket.Close();
            }
            Console.ReadKey();



        static Socket ConnectToServer(string serverIP, int serverPort)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            EndPoint localEP = new IPEndPoint(IPAddress.Any, 0);
            socket.Bind(localEP);
            socket.Connect(new IPEndPoint(IPAddress.Parse(serverIP), serverPort));
            return socket;
        }
    }

温馨提示:内容为网友见解,仅供参考
第1个回答  2014-04-14
在AcceptCallback方法中,一方面要用newSocket.BeginReceive方法开始接收,一方面要调用Socket.BeginAccept继续接收连接尝试。追问

这个我知道的,我在AcceptCallback中已经设置了allDone.set这样他会继续Socket.BeginAccept继续接收连接尝试 我问的意思是Socket.BeginAccept同时接收了多个连接,服务器就会出问题以后再用SET也没用了 请问出在哪里

追答

不清楚allDone里边写了些什么……对照下代码吧,这个刚刚测试了能连接多个端。


        /// <summary>
        /// 开启监听
        /// </summary>
        public void StartListen()
        {
            try
            {
                ServerListnener = new Socket(GetAddress().Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                ServerListnener.Bind(GetAddress());
                ServerListnener.Listen(200);
                
                ServerListnener.BeginAccept(new AsyncCallback(AcceptCallback), ServerListnener);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

 字数限制,后面加不上了……

追问

ServerListnener.BeginAccept这个一个只能连接一个客户端吧

追答public void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = ServerListnener.EndAccept(ar);
                handler.Send(Encoding.Unicode.GetBytes("已连接到服务器!"));  
                this.sockets.Add(handler);

                //buffer存储接收的数据,包装buffer与handler作为参数传递给ReceiveCallback
                byte[] buffer = new byte[10240];
                object[] obj = new object[2];
                obj[0] = buffer;
                obj[1] = handler;
                handler.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), obj);

                //重复回调,循环前面的操作
                Socket NewListener = (Socket)ar.AsyncState;
                NewListener.BeginAccept(new AsyncCallback(AcceptCallback), NewListener);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

追问

兄弟 这个我都写好了,我的问题是这样的,只到ServerListnener.Listen(200);这一步后面的代码不写,客户端那边也能连接成功的,这种成功我服务器上怎么知道

追答

Socket handler = ServerListnener.EndAccept(ar);
这个handler是客户端连接上了才会创建的。里边有这个连接的详细信息(双方IPEndPoint之类的)。
在这句后面写个Console.WriteLine("XXX已连接");之类的没有问题。

第2个回答  2014-04-14
很高兴协助你完成朋友

C# SOCKET 异步接收的问题
那么同步与异步分别应用于什么情况呢?假如用户的socket连接数据比较短暂的。一次连接直接发送数据的或客户端比较少的就使用同步假如用户的socket属于长时间连接的就使用异步方式

C# Socket 异步通讯
在异步RecVing方法中有两点可以改进:1)增加异常处理,目的是:即使发生异常也保证Socket能正常工作。2)调用 EndAceept返回的是正在与客户端连接的sockt private static void RecVing(IAsyncResult Result){ \/\/通过 result 获取socket。在这个socket上你启动了BeginAccept操作 Socket socket = Result....

C# C\/S网络编程 由于系统缓存空间不足或列队已满,不能执行套接字上的...
\/\/ 继续异步接收 ReceiveMsg();\/\/ 完成前一次异步接收EndReceive处理 UdpState udpReceiveState = iar.AsyncState as UdpState;\/\/……} 要注意的是:1)Socket异步接收处理过程中用到了.net framework内部线程池,而线程池中线程的数量是有限制的。2)ReceiveMsg中的 while(true)循环是多余的 3)Rec...

C#Socket无连接异步传输
而客户端却不但要知道服务器的IP 还要知道服务器用来监听的那个端口(PORT) 这样就形成了一个服务器ENDPOINT(IP+PORT) 然后自己生成一个SOCKET实例 再连接那个服务器ENDPOINT 再通过这个SOCKET实例传输自己的BYTE流 编IM还是很复杂的 尤其是线程和异步调用的问题 SOCKET只是第一步 和网页的那种伪IM完全不一...

C#socket异步怎么实现 线程间通信如何实现
基于C#的socket编程的TCP异步实现一、摘要 本篇博文阐述基于TCP通信协议的异步实现。二、实验平台 Visual Studio 2010三、异步通信实现原理及常用方法3.1 建立连接 在同步模式中,在服务器上使用Accept方法接入连接请求,而在客户端则使用Connect方法来连接服务器。相对地,在异步模式下,服务器可以使用BeginAccept方法和End...

C#Socket(tcp)异步批量发送文件问题
测试文件发送到Server和下载的情况基本差不多,这说明了在网络不好的情况处理发送大数据包似首容易产生错误,但看TCP\/IP协议讲解这情况似乎不存在,因为当一个发送数据超过某个值的时候,TCP会划分块进行传输并保证其顺序.但网络不好的情况测试结果接收的数据有错误,但处理的数据大小是正确的,也并没影响整个...

c#中tcp异步编程遇到异常问题,新手感觉很不得懂 希望大神能从浅显的角度...
tcpClient = new TcpClient(host,52888);host为我指定的ip 上面是你理解的有问题。第一:tcpClient = new TcpClient(AddressFamily.InterNetwork);这句话不是获得本机的ip地址,而是要创建一个使用ip版本4的寻址方案的TcpClient对象。这时只是定义这个对象,并没有建立连接 第二:tcpClient = new TcpClient(...

c#网络编程中的异常
1可能你的程序把一个端口,绑定了两次 2也可能是你的程序使用的端口在其他程序已经被使用 介意 把你的程序换成一个生僻的端口 ,如9999,看异常是否消失,如果是,则是第二种情况。如果不是,则仔细检查你的程序,是否在未释放端口的情况下,是否又进行了端口绑定的操作 ...

c#socket异步连接后怎样判断连接是否成功
} } private void connCallBack(IAsyncResult ar) { Socket s = (Socket)ar.AsyncState; try { s.EndConnect(ar); isConnected = s.Connected; } catch (Exception ex)

c#socket在使用TCP或UDP异步通信的时候SocketAsyncEventArgs和...
1、在使用SocketAsyncEventArgs进行TCP或UDP通讯的时候最常用的几个成员分别是:Buffer,BufferList,BytesTransferred,SocketError,UserToken,BytesTransferred属性,SetBuffer方法和Completed事件。2、SocketAsyncEventArgs接收和发送数据都需要设置buffer,一般用SetBuffer方法或设置BufferList。通过Completed来查看完成情况,而...

相似回答