加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[C#] SocketAsyncServer 与 SocketAsyncClient

(2012-02-23 10:56:59)
标签:

c

sockets

增强

分类: 学习资料-分享

 最近工作需要,需要学习c# sockets 编程,网络上找到了SocketAsyncServer  与 SocketAsyncClient 扩展类,记录下:

Server端:

//SocketListener.cs

using System;

using System.IO;

using System.Net.Sockets;

using System.Threading;

using System.Net;

using System.Text;


namespace SocketAsyncServer

{

    /// <summary>

    /// Based on example from http://msdn2.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

    /// Implements the connection logic for the socket server.  

    /// After accepting a connection, all data read from the client is sent back. 

    /// The read and echo back to the client pattern is continued until the client disconnects.

    /// </summary>

    internal sealed class SocketListener

    {

        /// <summary>

        /// The socket used to listen for incoming connection requests.

        /// </summary>

        private Socket listenSocket;


        /// <summary>

        /// Mutex to synchronize server execution.

        /// </summary>

        private static Mutex mutex = new Mutex();


        /// <summary>

        /// Buffer size to use for each socket I/O operation.

        /// </summary>

        private Int32 bufferSize;


        /// <summary>

        /// The total number of clients connected to the server.

        /// </summary>

        private Int32 numConnectedSockets;


        /// <summary>

        /// the maximum number of connections the sample is designed to handle simultaneously.

        /// </summary>

        private Int32 numConnections;


        /// <summary>

        /// Pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations.

        /// </summary>

        private SocketAsyncEventArgsPool readWritePool;


        /// <summary>

        /// Controls the total number of clients connected to the server.

        /// </summary>

        private Semaphore semaphoreAcceptedClients;


        /// <summary>

        /// Create an uninitialized server instance.  

        /// To start the server listening for connection requests

        /// call the Init method followed by Start method.

        /// </summary>

        /// <param name="numConnections">Maximum number of connections to be handled simultaneously.</param>

        /// <param name="bufferSize">Buffer size to use for each socket I/O operation.</param>

        internal SocketListener(Int32 numConnections, Int32 bufferSize)

        {

            this.numConnectedSockets = 0;

            this.numConnections = numConnections;

            this.bufferSize = bufferSize;


            this.readWritePool = new SocketAsyncEventArgsPool(numConnections);

            this.semaphoreAcceptedClients = new Semaphore(numConnections, numConnections);


            // Preallocate pool of SocketAsyncEventArgs objects.

            for (Int32 i = 0; i < this.numConnections; i++)

            {

                SocketAsyncEventArgs readWriteEventArg = new SocketAsyncEventArgs();

                readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnIOCompleted);

                readWriteEventArg.SetBuffer(new Byte[this.bufferSize], 0, this.bufferSize);


                // Add SocketAsyncEventArg to the pool.

                this.readWritePool.Push(readWriteEventArg);

            }

        }


        /// <summary>

        /// Close the socket associated with the client.

        /// </summary>

        /// <param name="e">SocketAsyncEventArg associated with the completed send/receive operation.</param>

        private void CloseClientSocket(SocketAsyncEventArgs e)

        {

            Token token = e.UserToken as Token;

            this.CloseClientSocket(token, e);

        }


        private void CloseClientSocket(Token token, SocketAsyncEventArgs e)

        {

            token.Dispose();


            // Decrement the counter keeping track of the total number of clients connected to the server.

            this.semaphoreAcceptedClients.Release();

            Interlocked.Decrement(ref this.numConnectedSockets);

            string ip = "";

            int handle = (int)token.Connection.Handle;

            Console.WriteLine("A client Handle[{1}] has been disconnected from the server. There are {0} clients connected to the server", this.numConnectedSockets,handle.ToString());


            // Free the SocketAsyncEventArg so they can be reused by another client.

            this.readWritePool.Push(e);

        }


        /// <summary>

        /// Callback method associated with Socket.AcceptAsync 

        /// operations and is invoked when an accept operation is complete.

        /// </summary>

        /// <param name="sender">Object who raised the event.</param>

        /// <param name="e">SocketAsyncEventArg associated with the completed accept operation.</param>

        private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)

        {

            this.ProcessAccept(e);

        }


        /// <summary>

        /// Callback called whenever a receive or send operation is completed on a socket.

        /// </summary>

        /// <param name="sender">Object who raised the event.</param>

        /// <param name="e">SocketAsyncEventArg associated with the completed send/receive operation.</param>

        private void OnIOCompleted(object sender, SocketAsyncEventArgs e)

        {

            // Determine which type of operation just completed and call the associated handler.

            switch (e.LastOperation)

            {

                case SocketAsyncOperation.Receive:

                    this.ProcessReceive(e);

                    break;

                case SocketAsyncOperation.Send:

                    this.ProcessSend(e);

                    break;

                default:

                    throw new ArgumentException("The last operation completed on the socket was not a receive or send");

            }

        }


        /// <summary>

        /// Process the accept for the socket listener.

        /// </summary>

        /// <param name="e">SocketAsyncEventArg associated with the completed accept operation.</param>

        private void ProcessAccept(SocketAsyncEventArgs e)

        {

            Socket s = e.AcceptSocket;

            if (s.Connected)

            {

                try

                {

                    SocketAsyncEventArgs readEventArgs = this.readWritePool.Pop();

                    if (readEventArgs != null)

                    {

                        // Get the socket for the accepted client connection and put it into the 

                        // ReadEventArg object user token.

                        readEventArgs.UserToken = new Token(s, this.bufferSize);


                        Interlocked.Increment(ref this.numConnectedSockets);


                        string ip = s.RemoteEndPoint.ToString();

                        int handle = (int)s.Handle;

                        Console.WriteLine("Client[{1}] Handle[{2}] connection accepted. There are {0} clients connected to the server\n",

                            this.numConnectedSockets,ip,handle.ToString());


                        if (!s.ReceiveAsync(readEventArgs))

                        {

                            this.ProcessReceive(readEventArgs);

                        }

                    }

                    else

                    {

                        Console.WriteLine("There are no more available sockets to allocate.");

                    }

                }

                catch (SocketException ex)

                {

                    Token token = e.UserToken as Token;

                    Console.WriteLine("Error when processing data received from {0}:\r\n{1}", token.Connection.RemoteEndPoint, ex.ToString());

                }

                catch (Exception ex)

                {

                    Console.WriteLine(ex.ToString());

                }


                // Accept the next connection request.

                this.StartAccept(e);

            }

        }


        private void ProcessError(SocketAsyncEventArgs e)

        {

            Token token = e.UserToken as Token;

            IPEndPoint localEp = token.Connection.LocalEndPoint as IPEndPoint;


            this.CloseClientSocket(token, e);


            Console.WriteLine("Socket error {0} on endpoint {1} during {2}.", (Int32)e.SocketError, localEp, e.LastOperation);

        }


        /// <summary>

        /// This method is invoked when an asynchronous receive operation completes. 

        /// If the remote host closed the connection, then the socket is closed.  

        /// If data was received then the data is echoed back to the client.

        /// </summary>

        /// <param name="e">SocketAsyncEventArg associated with the completed receive operation.</param>

        private void ProcessReceive(SocketAsyncEventArgs e)

        {

            // Check if the remote host closed the connection.

            if (e.BytesTransferred > 0)

            {

                if (e.SocketError == SocketError.Success)

                {

                    Token token = e.UserToken as Token;

                    token.SetData(e);


                    Socket s = token.Connection;

                    

                    if (s.Available == 0)

                    {

                        // Set return buffer.

                        token.ProcessData(e);

                        if (!s.SendAsync(e))

                        {

                            // Set the buffer to send back to the client.

                            this.ProcessSend(e);

                        }

                    }

                    else if (!s.ReceiveAsync(e))

                    {

                        // Read the next block of data sent by client.

                        this.ProcessReceive(e);

                    }

                }

                else

                {

                    this.ProcessError(e);

                }

            }

            else

            {

                this.CloseClientSocket(e);

            }

        }


        /// <summary>

        /// This method is invoked when an asynchronous send operation completes.  

        /// The method issues another receive on the socket to read any additional 

        /// data sent from the client.

        /// </summary>

        /// <param name="e">SocketAsyncEventArg associated with the completed send operation.</param>

        private void ProcessSend(SocketAsyncEventArgs e)

        {

            if (e.SocketError == SocketError.Success)

            {

                // Done echoing data back to the client.

                Token token = e.UserToken as Token;


                if (!token.Connection.ReceiveAsync(e))

                {

                    // Read the next block of data send from the client.

                    this.ProcessReceive(e);

                }

            }

            else

            {

                this.ProcessError(e);

            }

        }


        /// <summary>

        /// Starts the server listening for incoming connection requests.

        /// </summary>

        /// <param name="port">Port where the server will listen for connection requests.</param>

        internal void Start(Int32 port)

        {

            // Get host related information.

            IPAddress[] addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;


            // Get endpoint for the listener.

            IPEndPoint localEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);


            // Create the socket which listens for incoming connections.

            this.listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            this.listenSocket.ReceiveBufferSize = this.bufferSize;

            this.listenSocket.SendBufferSize = this.bufferSize;


            if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)

            {

                // Set dual-mode (IPv4 & IPv6) for the socket listener.

                // 27 is equivalent to IPV6_V6ONLY socket option in the winsock snippet below,

                // based on http://blogs.msdn.com/wndp/archive/2006/10/24/creating-ip-agnostic-applications-part-2-dual-mode-sockets.aspx

                this.listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);

                this.listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));

            }

            else

            {

                // Associate the socket with the local endpoint.

                this.listenSocket.Bind(localEndPoint);

            }


            // Start the server.

            this.listenSocket.Listen(this.numConnections);


            // Post accepts on the listening socket.

            this.StartAccept(null);


            // Blocks the current thread to receive incoming messages.

            mutex.WaitOne();

        }


        /// <summary>

        /// Begins an operation to accept a connection request from the client.

        /// </summary>

        /// <param name="acceptEventArg">The context object to use when issuing 

        /// the accept operation on the server's listening socket.</param>

        private void StartAccept(SocketAsyncEventArgs acceptEventArg)

        {

            if (acceptEventArg == null)

            {

                acceptEventArg = new SocketAsyncEventArgs();

                acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);

            }

            else

            {

                // Socket must be cleared since the context object is being reused.

                acceptEventArg.AcceptSocket = null;

            }


            this.semaphoreAcceptedClients.WaitOne();

            if (!this.listenSocket.AcceptAsync(acceptEventArg))

            {

                this.ProcessAccept(acceptEventArg);

            }

        }


        /// <summary>

        /// Stop the server.

        /// </summary>

        internal void Stop()

        {

            this.listenSocket.Close();

            mutex.ReleaseMutex();

        }

    }

}

//Token.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Globalization;

namespace SocketAsyncServer
{
    delegate void ProcessData(SocketAsyncEventArgs args);

    /// <summary>
    /// Token for use with SocketAsyncEventArgs.
    /// </summary>
    internal sealed class Token : IDisposable
    {
        private Socket connection;

        private StringBuilder sb;

        private Int32 currentIndex;

        /// <summary>
        /// Class constructor.
        /// </summary>
        /// <param name="connection">Socket to accept incoming data.</param>
        /// <param name="bufferSize">Buffer size for accepted data.</param>
        internal Token(Socket connection, Int32 bufferSize)
        {
            this.connection = connection;
            this.sb = new StringBuilder(bufferSize);
        }

        /// <summary>
        /// Accept socket.
        /// </summary>
        internal Socket Connection
        {
            get { return this.connection; }
        }

        /// <summary>
        /// Process data received from the client.
        /// </summary>
        /// <param name="args">SocketAsyncEventArgs used in the operation.</param>
        internal void ProcessData(SocketAsyncEventArgs args)
        {
            // Get the message received from the client.
            String received = this.sb.ToString();

            int handle = (int)this.Connection.Handle;
            //int handle=args.
            //TODO Use message received to perform a specific operation.
            Console.WriteLine("Received From Handle[{2}] Message: "{0}". The server has read {1} bytes.", received, received.Length,handle.ToString());

            Byte[] sendBuffer = Encoding.ASCII.GetBytes("Return "+ received);
            args.SetBuffer(sendBuffer, 0, sendBuffer.Length);

            // Clear StringBuffer, so it can receive more data from a keep-alive connection client.
            sb.Length = 0;
            this.currentIndex = 0;
        }

        /// <summary>
        /// Set data received from the client.
        /// </summary>
        /// <param name="args">SocketAsyncEventArgs used in the operation.</param>
        internal void SetData(SocketAsyncEventArgs args)
        {
            Int32 count = args.BytesTransferred;

            if ((this.currentIndex + count) > this.sb.Capacity)
            {
                throw new ArgumentOutOfRangeException("count",
                    String.Format(CultureInfo.CurrentCulture, "Adding {0} bytes on buffer which has {1} bytes, the listener buffer will overflow.", count, this.currentIndex));
            }

            sb.Append(Encoding.ASCII.GetString(args.Buffer, args.Offset, count));
            this.currentIndex += count;
        }

        #region IDisposable Members

        /// <summary>
        /// Release instance.
        /// </summary>
        public void Dispose()
        {
            try
            {
                this.connection.Shutdown(SocketShutdown.Send);
            }
            catch (Exception)
            {
                // Throw if client has closed, so it is not necessary to catch.
            }
            finally
            {
                this.connection.Close();
            }
        }

        #endregion
    }
}

//SocketAsyncEventArgsPool.cs
using System;
using System.Collections.Generic;
using System.Net.Sockets;

namespace SocketAsyncServer
{
    /// <summary>
    /// Based on example from http://msdn2.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.socketasynceventargs.aspx
    /// Represents a collection of reusable SocketAsyncEventArgs objects.  
    /// </summary>
    internal sealed class SocketAsyncEventArgsPool
    {
        /// <summary>
        /// Pool of SocketAsyncEventArgs.
        /// </summary>
        Stack<SocketAsyncEventArgs> pool;

        /// <summary>
        /// Initializes the object pool to the specified size.
        /// </summary>
        /// <param name="capacity">Maximum number of SocketAsyncEventArgs objects the pool can hold.</param>
        internal SocketAsyncEventArgsPool(Int32 capacity)
        {
            this.pool = new Stack<SocketAsyncEventArgs>(capacity);
        }

        /// <summary>
        /// Removes a SocketAsyncEventArgs instance from the pool.
        /// </summary>
        /// <returns>SocketAsyncEventArgs removed from the pool.</returns>
        internal SocketAsyncEventArgs Pop()
        {
            lock (this.pool)
            {
                if (this.pool.Count > 0)
                {
                    return this.pool.Pop();
                }
                else
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// Add a SocketAsyncEventArg instance to the pool. 
        /// </summary>
        /// <param name="item">SocketAsyncEventArgs instance to add to the pool.</param>
        internal void Push(SocketAsyncEventArgs item)
        {
            if (item == null) 
           
                throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); 
            }
            lock (this.pool)
            {
                this.pool.Push(item);
            }
        }
    }
}


Client端:
//SocketClient.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SocketAsyncClient
{
    /// <summary>
    /// Implements the connection logic for the socket client.
    /// </summary>
    internal sealed class SocketClient : IDisposable
    {
        /// <summary>
        /// Constants for socket operations.
        /// </summary>
        private const Int32 ReceiveOperation = 1, SendOperation = 0;

        /// <summary>
        /// The socket used to send/receive messages.
        /// </summary>
        private Socket clientSocket;

        /// <summary>
        /// Flag for connected socket.
        /// </summary>
        private Boolean connected = false;

        /// <summary>
        /// Listener endpoint.
        /// </summary>
        private IPEndPoint hostEndPoint;

        /// <summary>
        /// Signals a connection.
        /// </summary>
        private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false); 

        /// <summary>
        /// Signals the send/receive operation.
        /// </summary>
        private static AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[]
        {
            new AutoResetEvent(false),
            new AutoResetEvent(false)
        };

        public bool ConnectState
        {
            get
            {
                return this.connected;
            }
        }
        /// <summary>
        /// Create an uninitialized client instance.  
        /// To start the send/receive processing
        /// call the Connect method followed by SendReceive method.
        /// </summary>
        /// <param name="hostName">Name of the host where the listener is running.</param>
        /// <param name="port">Number of the TCP port from the listener.</param>
        internal SocketClient(String hostName, Int32 port)
        {
            // Get host related information.
            IPHostEntry host = Dns.GetHostEntry(hostName);

            // Addres of the host.
            IPAddress[] addressList = host.AddressList;

            // Instantiates the endpoint and socket.
            this.hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
            this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }

        /// <summary>
        /// Connect to the host.
        /// </summary>
        /// <returns>True if connection has succeded, else false.</returns>
        internal void Connect()
        {
            SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();

            connectArgs.UserToken = this.clientSocket;
            connectArgs.RemoteEndPoint = this.hostEndPoint;
            connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);

            clientSocket.ConnectAsync(connectArgs);
            autoConnectEvent.WaitOne();

            SocketError errorCode = connectArgs.SocketError;
            if (errorCode != SocketError.Success)
            {
                throw new SocketException((Int32)errorCode);
            }
        }
        
        /// <summary>
        /// Disconnect from the host.
        /// </summary>
        internal void Disconnect()
        {
            clientSocket.Disconnect(false);
        }

        private void OnConnect(object sender, SocketAsyncEventArgs e)
        {
            // Signals the end of connection.
            autoConnectEvent.Set();

            // Set the flag for socket connected.
            this.connected = (e.SocketError == SocketError.Success);
        }

        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            // Signals the end of receive.
            autoSendReceiveEvents[SendOperation].Set();
        }

        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            // Signals the end of send.
            autoSendReceiveEvents[ReceiveOperation].Set();

            if (e.SocketError == SocketError.Success)
            {
                if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    // Prepare receiving.
                    Socket s = e.UserToken as Socket;

                    byte[] receiveBuffer = new byte[255];
                    e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
                    e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                    s.ReceiveAsync(e);
                }
            }
            else
            {
                this.ProcessError(e);
            }
        }

        /// <summary>
        /// Close socket in case of failure and throws a SockeException according to the SocketError.
        /// </summary>
        /// <param name="e">SocketAsyncEventArg associated with the failed operation.</param>
        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s.Connected)
            {
                // close the socket associated with the client
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    // throws if client process has already closed
                }
                finally
                {
                    if (s.Connected)
                    {
                        s.Close();
                    }
                }
            }

            // Throw the SocketException
            throw new SocketException((Int32)e.SocketError);
        }

        /// <summary>
        /// Exchange a message with the host.
        /// </summary>
        /// <param name="message">Message to send.</param>
        /// <returns>Message sent by the host.</returns>
        internal String SendReceive(String message)
        {
            if (this.connected)
            {
                // Create a buffer to send.
                Byte[] sendBuffer = Encoding.ASCII.GetBytes(message);

                // Prepare arguments for send/receive operation.
                SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
                completeArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
                completeArgs.UserToken = this.clientSocket;
                completeArgs.RemoteEndPoint = this.hostEndPoint;
                completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

                // Start sending asyncronally.
                clientSocket.SendAsync(completeArgs);

                // Wait for the send/receive completed.
                AutoResetEvent.WaitAll(autoSendReceiveEvents);

                // Return data from SocketAsyncEventArgs buffer.
                return Encoding.ASCII.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);
            }
            else
            {
                throw new SocketException((Int32)SocketError.NotConnected);
            }
        }

        #region IDisposable Members

        /// <summary>
        /// Disposes the instance of SocketClient.
        /// </summary>
        public void Dispose()
        {
            autoConnectEvent.Close();
            autoSendReceiveEvents[SendOperation].Close();
            autoSendReceiveEvents[ReceiveOperation].Close();
            if (this.clientSocket.Connected)
            {
                this.clientSocket.Close();
            }
        }

        #endregion
    }
}

//Program.cs
using System;

namespace SocketAsyncClient
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                //String host = args[0];
                String host="192.168.100.213";
                //Int32 port = Convert.ToInt32(args[1]);
                Int32 port = 9900;
                Int16 iterations = 1;
                //if (args.Length == 3)
                //{
                //    iterations = Convert.ToInt16(args[2]);
                //}

                using (SocketClient sa = new SocketClient(host, port))
                {
                    sa.Connect();

                    for (Int32 i = 0; i < iterations; i++)
                    {
                        Console.WriteLine(sa.SendReceive("Message #" + i.ToString()));
                    }
                    //Console.Read();
                    string cmd = Console.ReadLine().ToUpper();
                    if (cmd== "STOP")
                    {
                        sa.Disconnect();
                    }
                    else 
                    {
                        Console.WriteLine(sa.SendReceive("Message # ""+cmd ));
                    }
                    //Console.WriteLine("Press any key to terminate the client process...");
                    //Console.Read();
                }
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("Usage: SocketAsyncClient <host> <port> [iterations]");
            }
            catch (FormatException)
            {
                Console.WriteLine("Usage: SocketAsyncClient <host> <port> [iterations]." +
                    "\r\n\t<host> Name of the host to connect." +
                    "\r\n\t<port> Numeric value for the host listening TCP port." +
                    "\r\n\t[iterations] Number of iterations to the host.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message);
            }
        }
    }
}

ps:
  步骤1.服务器端监听端口,等待连接 
SocketListener sl = new SocketListener(numConnections, bufferSize);
        sl.Start(port);
http://s5/bmiddle/7744890bgb998f96913c4&690SocketAsyncServer 与 SocketAsyncClient" TITLE="[C#] SocketAsyncServer 与 SocketAsyncClient" />

 步骤2 客户端连接至服务器

SocketClient sa = new SocketClient(host, port)

sa.Connect();

http://s13/bmiddle/7744890bgb999007313ac&690SocketAsyncServer 与 SocketAsyncClient" TITLE="[C#] SocketAsyncServer 与 SocketAsyncClient" />

 步骤3:客户端发送数据
sa.SendReceive("Message #" + i.ToString())
http://s16/bmiddle/7744890bgb999077f921f&690SocketAsyncServer 与 SocketAsyncClient" TITLE="[C#] SocketAsyncServer 与 SocketAsyncClient" />
 步骤4 服务器返回数据给客户端:
Byte[] sendBuffer = Encoding.ASCII.GetBytes("Return "+ received); args.SetBuffer(sendBuffer, 0, sendBuffer.Length);
http://s15/bmiddle/7744890bgb999078bc78e&690SocketAsyncServer 与 SocketAsyncClient" TITLE="[C#] SocketAsyncServer 与 SocketAsyncClient" />

 步骤5:断开连接
http://s8/bmiddle/7744890bgb99911993c67&690SocketAsyncServer 与 SocketAsyncClient" TITLE="[C#] SocketAsyncServer 与 SocketAsyncClient" />

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有