C#Socket 异步代码示例

本文深入探讨了在C#环境下利用SocketAsyncEventArgs和IAsyncResult进行网络套接字异步编程的技术细节,包括服务器端与客户端的实现方式,以及如何在VS中调试启动多个项目。通过实例代码演示了如何使用这些异步方法来提高程序性能,减少界面卡顿,提供流畅的用户体验。

    写在最前:以前在C\C++控制台,简单MFC和C#程序里简单接触了网络套接字编程。了解了网络套接字是这样一个流程 打开 -> 发送/接收->关闭 的简单过程。由于网络传输速度影响,在网络套接字的同步调用时会对程序的使用性产生影响(程序界面被卡死),后来知道可以使用异步编程的概念——通过开线程来达到不阻塞用户界面的效果。后来在接触网络套接字编程的次数多了以后,在C#.NET环境中发现Socket竟然多出了两类方法 XXXXAsync 和 BeginXXXX / EndXXXX。接下来就用代码演示一下这两类方法如何使用~

    接下来的页面会很长,能扯一点的现在这扯一点。这两类方法分别对应SocketAsyncEventArgs  、 IAsyncResult。我暂时也讲不出什么,有问题问吧还是。文章最后有如何在vs一个解决方案中调试启动多个项目(这可能是很多人没有注意到的操作)。

So long,Coding

首先是XXXXAsync的,

  Server

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace SocketTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket serverSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            serverSk.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596));
            serverSk.Listen(1);

            SocketAsyncEventArgs AcceptSAE = new SocketAsyncEventArgs();
            AcceptSAE.Completed += new EventHandler(AcceptSAE_Completed);
            serverSk.AcceptAsync(AcceptSAE);

            Console.ReadLine();
        }

        static void AcceptSAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket serverSk = sender as Socket;
            if (e.SocketError == SocketError.Success)
            {
                serverSk = e.AcceptSocket;
                SocketAsyncEventArgs SendSAE = new SocketAsyncEventArgs();
                byte[] data = System.Text.Encoding.UTF8.GetBytes("OK,Just Put IT!");
                SendSAE.SetBuffer(data, 0, data.Length);
                SendSAE.Completed += new EventHandler(SendSAE_Completed);

                SocketAsyncEventArgs RecieveSAE = new SocketAsyncEventArgs();
                byte[] buffer = new byte[2048];//因为我们不知道上面的字符串究竟会场生多少字节,这里我们就设置一个理论上可以满足大小的值2046。
                RecieveSAE.SetBuffer(buffer, 0, buffer.Length);
                RecieveSAE.Completed += new EventHandler(RecieveSAE_Completed);

                serverSk.ReceiveAsync(RecieveSAE);
                serverSk.SendAsync(SendSAE);
            }
            else
                Console.WriteLine("接受网络套接字连接请求失败!具体原因请自己调试!");
        }


        static void RecieveSAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket sk = sender as Socket;
            byte[] data = e.Buffer;  //注意这里,如何取关联到套接字的发送接受的缓冲区中的值。
            string msg = System.Text.Encoding.UTF8.GetString(data);
            Console.WriteLine("Message received: " + msg);

           // sk.DisconnectAsync();//你看看 该怎么做呢?
        }

        static void SendSAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket sk = sender as Socket;
            if (e.SocketError == SocketError.Success)
            {
                Console.WriteLine("Send complete!");


                byte[] data = e.Buffer;  //注意这里,如何取关联到套接字的发送接受的缓冲区中的值。
                string msg = System.Text.Encoding.UTF8.GetString(data);
                Console.WriteLine("What you sent: " + msg);
            }
        }
    }
}

Client:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace SocketTestTwo
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket clientSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            SocketAsyncEventArgs ConnectSAE = new SocketAsyncEventArgs();
            ConnectSAE.RemoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596);
            ConnectSAE.Completed += new EventHandler(ConnectSAE_Completed);
            clientSk.ConnectAsync(ConnectSAE);
            Console.ReadLine();
        }

        static void ConnectSAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket clientSk = sender as Socket;
            if (e.SocketError == SocketError.Success && clientSk.Connected)
            {
                SocketAsyncEventArgs SendSAE = new SocketAsyncEventArgs();
                byte[] data = System.Text.Encoding.UTF8.GetBytes("I want put all funy things together!");
                SendSAE.SetBuffer(data, 0, data.Length);
                SendSAE.Completed += new EventHandler(SendSAE_Completed);

                SocketAsyncEventArgs RecieveSAE = new SocketAsyncEventArgs();
                byte[] buffer = new byte[2048];//因为我们不知道上面的字符串究竟会场生多少字节,这里我们就设置一个理论上可以满足大小的值2046。
                RecieveSAE.SetBuffer(buffer, 0, buffer.Length);
                RecieveSAE.Completed += new EventHandler(RecieveSAE_Completed);

                //先调用异步接收,再调用异步发送。让你体验到异步明显非一般的感觉。
                clientSk.ReceiveAsync(RecieveSAE);
                clientSk.SendAsync(SendSAE);
            }
        }

        static void RecieveSAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket sk = sender as Socket;
            byte[] data = e.Buffer;  //注意这里,如何取关联到套接字的发送接受的缓冲区中的值。
            string msg = System.Text.Encoding.UTF8.GetString(data);
            Console.WriteLine("Message received: "+msg);

            //sk.DisconnectAsync();//你看看 该怎么做呢?
        }

        static void SendSAE_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket sk = sender as Socket;
            if (e.SocketError == SocketError.Success)
            {
                Console.WriteLine("Send complete!");
            }
        }

        
    }
}

2011070520381445.jpg

然后是BenginXXXX 和 EndXXXX的

Server

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace SocketTestt
{
    public class MyObject
    {
        #region 类字段

        private Socket _Socket;
        private string _MyName = "";
        private byte[] _Buffer;


        #endregion

        #region 类属性

        public Socket Socket
        {
            get { return _Socket; }
            set { _Socket = value; }
        }


        public byte[] Buffer
        {
            get { return _Buffer; }
            set { _Buffer = value; }
        }


        public string MyName
        {
            get { return _MyName; }
            set { _MyName = value; }
        }

        #endregion

        #region 构造函数

        public MyObject(Socket socket, string myName)
        {
            _Socket = socket;
            _MyName = myName;
        }
        public MyObject(Socket socket, string myName,byte[] buffer)
        {
            _Socket = socket;
            _MyName = myName;
            _Buffer = buffer;
        }

        #endregion
    }

    class Program
    {
        static void Main(string[] args)
        {
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596));
            server.Listen(1);

            server.BeginAccept(new AsyncCallback(AcceptComplete),new MyObject(server,"开始连接了"));

            Console.ReadLine();

        }


        static void AcceptComplete(IAsyncResult ar)
        {
            MyObject myObj = ar.AsyncState as MyObject;
            Socket serverSk = myObj.Socket.EndAccept(ar);

            byte[] buffer = new byte[2048]; //虽然不知道会收到多少,但是多了总比少了好。

            serverSk.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecievedComplete), new MyObject(serverSk, "开始接收了", buffer));

            byte[] datas = System.Text.Encoding.UTF8.GetBytes("I know , Just put it!");
            serverSk.BeginSend(datas, 0, datas.Length, SocketFlags.None, new AsyncCallback(SendComplete), new MyObject(serverSk, "开始发送了", datas));

        }

        static void SendComplete(IAsyncResult ar)
        {
            MyObject myObj = ar.AsyncState as MyObject;
            Socket sk = myObj.Socket;
            
            int sended = sk.EndSend(ar);

            Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
        }

        static void RecievedComplete(IAsyncResult ar)
        {

            MyObject myObj = ar.AsyncState as MyObject;
            Socket sk = myObj.Socket;

            int recieved = sk.EndReceive(ar);

            Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
        }
    }
}
Client
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace SocketTwo
{
    public class MyObject
    {
        #region 类字段

        private Socket _Socket;
        private string _MyName = "";
        private byte[] _Buffer;


        #endregion

        #region 类属性

        public Socket Socket
        {
            get { return _Socket; }
            set { _Socket = value; }
        }


        public byte[] Buffer
        {
            get { return _Buffer; }
            set { _Buffer = value; }
        }


        public string MyName
        {
            get { return _MyName; }
            set { _MyName = value; }
        }

        #endregion

        #region 构造函数

        public MyObject(Socket socket, string myName)
        {
            _Socket = socket;
            _MyName = myName;
        }
        public MyObject(Socket socket, string myName, byte[] buffer)
        {
            _Socket = socket;
            _MyName = myName;
            _Buffer = buffer;
        }

        #endregion
    }

    class Program
    {
        static void Main(string[] args)
        {
            Socket clientSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            clientSk.BeginConnect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596), new AsyncCallback(ConnectComplete), new MyObject(clientSk, "开始连接了"));

            Console.ReadLine();
        }


        static void ConnectComplete(IAsyncResult ar)
        {
            MyObject myObj = ar.AsyncState as MyObject;
            Socket clientSk = myObj.Socket;

            byte[] datas = System.Text.Encoding.UTF8.GetBytes("I always want put things together!");
            clientSk.BeginSend(datas, 0, datas.Length, SocketFlags.None, new AsyncCallback(SendComplete), new MyObject(clientSk, "开始发送了", datas));


            byte[] buffer = new byte[2048]; //虽然不知道会收到多少,但是多了总比少了好。

            clientSk.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecievedComplete), new MyObject(clientSk, "开始接收了", buffer));

        }

        static void SendComplete(IAsyncResult ar)
        {
            MyObject myObj = ar.AsyncState as MyObject;
            Socket sk = myObj.Socket;

            int sended = sk.EndSend(ar);

            Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
        }

        static void RecievedComplete(IAsyncResult ar)
        {

            MyObject myObj = ar.AsyncState as MyObject;
            Socket sk = myObj.Socket;

            int recieved = sk.EndReceive(ar);

            Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
        }
    }
}

2011070520384758.jpg

 The end.

附:

启动第一个项目

2011070608171267.jpg

启动第二个...第N个

2011070608173894.jpg

代码下载

转载于:https://www.cnblogs.com/klvk/archive/2011/07/05/2098632.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值