中易网

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

答案:3  悬赏:40  
解决时间 2021-01-08 09:42
关于c#的Socket异步网络编程问题
最佳答案
这样的写法有点问题:
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发生异常,异常信息:
{0}", e.Message);
            }
            finally
            {
                //继续异步Accept
                socket.BeginAccept(AcceptAsync, socket);
            }
        }

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

    /// 
    /// 事件参数:接收客户端连接后的事件参数
    /// 

    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;
        }
    }
全部回答
很高兴协助你完成朋友
在AcceptCallback方法中,一方面要用newSocket.BeginReceive方法开始接收,一方面要调用Socket.BeginAccept继续接收连接尝试。追问这个我知道的,我在AcceptCallback中已经设置了allDone.set这样他会继续Socket.BeginAccept继续接收连接尝试 我问的意思是Socket.BeginAccept同时接收了多个连接,服务器就会出问题以后再用SET也没用了 请问出在哪里追答
不清楚allDone里边写了些什么……对照下代码吧,这个刚刚测试了能连接多个端。

        /// 
        /// 开启监听
        /// 

        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已连接");之类的没有问题。
我要举报
如以上问答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
一审放弃鉴定权利,二审中可否申请鉴定求解
键入用于从源数据库选择数据sql的语句 怎样写
qq邮箱里的附件如何用迅雷下载?
长乐柠檬春天分店小烧货在哪
杭州附近有什么好玩的地方???
申通快递(西脑包康乐小区)地址在哪,我要去那
用photoshop打开一个图片的时候,上边总是有
金丝肉松饼的配方
我喜欢的女孩叫赵思炜我想用跟她名字有关系的
在经期拔牙会怎样
LOL这游戏可以杀队友吗
古早味全鲜宴地址在什么地方,想过去办事
2×60万千瓦燃煤发电机组是什么意思?
巧算:24x23 1分之24 23x23
真正学佛的人是不是很少?
推荐资讯
3000和志骏有什么区别?
书包有可以折叠式的吗?
wow4.3右上角增益如何全部显示
摄影人为什么都这么疯狂
解道的彭晨阳(Banq)是Java顶级高手吗
2011年职称英语考试准考证怎么查
“人必自尊而人尊之,人必尊人而人尊之。”从
仙城工商所地址在什么地方,我要处理点事
1985到2005的电脑怎么从做系统
少先队队歌的含义
苹果5打电话为什么会自动关机
假官舟贩盐的假是什么意思
手机登qq时,显示手机磁盘不足,清理后重新登
刺客的套装怎么选啊?