C#使用Socket发送和接收TCP数据示例(异步版)

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

namespace ConsoleApplication1
{
    public class StateObject
    {
        public Socket workSocket = null;
        public byte[] buffer = new byte[1024];
        public List<byte> data = new List<byte>();
        //public const int BufferSize = 1024;
        //public StringBuilder sb = new StringBuilder();
    }

    /// <summary>
    /// 服务端
    /// </summary>
    public static class Server
    {
        private static Encoding encode = Encoding.Default;
        private static ManualResetEvent acceptDone = new ManualResetEvent(false);
        private static ManualResetEvent receiveDone = new ManualResetEvent(false);
        private static ManualResetEvent sendDone = new ManualResetEvent(false);
        private static byte[] endmark = new byte[] { 0x3C, 0x45, 0x4F, 0x46, 0x3E }; //约定结束符

        public static void Listen(int port)
        {
            Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listenSocket.Bind(new IPEndPoint(IPAddress.Any, port));
            listenSocket.Listen(100);
            Console.WriteLine("Listen " + port + " ...");

            while (true)
            {
                acceptDone.Reset();
                listenSocket.BeginAccept(EndAccept, listenSocket);
                acceptDone.WaitOne();
            }
        }

        #region callback methods

        private static void EndAccept(IAsyncResult ar)
        {
            Socket listener = (Socket)ar.AsyncState;
            Socket socket = listener.EndAccept(ar);//必须调用EndAccept获取新的Socket对象才可以收发数据

            StateObject state = new StateObject();
            state.workSocket = socket;
            socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);

            acceptDone.Set();
            receiveDone.WaitOne();
        }

        private static void EndReceive(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket socket = state.workSocket;

            int length = socket.EndReceive(ar);
            for (int j = 0; j < length; j++)
            {
                state.data.Add(state.buffer[j]);
            }
            if (!IsEnd(state.data.ToArray()))
            {
                socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
            }
            else
            {
                if (state.data.Count > 0)
                {
                    string receiveData = encode.GetString(state.data.ToArray(), 0, state.data.Count - endmark.Length);
                    Console.WriteLine("Receive:" + receiveData);
                    byte[] responseData = AddEndMark("ok");
                    socket.BeginSend(responseData, 0, responseData.Length, SocketFlags.None, EndSend, socket);
                }

                receiveDone.Set();
                sendDone.WaitOne();
            }
        }

        private static void EndSend(IAsyncResult ar)
        {
            Socket socket = (Socket)ar.AsyncState;
            socket.EndSend(ar);
            DestroySocket(socket);

            sendDone.Set();
        }

        #endregion

        #region private methods

        private static void DestroySocket(Socket socket)
        {
            if (socket != null)
            {
                if (socket.Connected)
                {
                    socket.Shutdown(SocketShutdown.Both);
                }
                socket.Close();
            }
        }

        public static byte[] AddEndMark(string data)
        {
            byte[] databytes = encode.GetBytes(data);
            byte[] result = new byte[databytes.Length + endmark.Length];
            Array.Copy(databytes, 0, result, 0, databytes.Length);
            Array.Copy(endmark, 0, result, databytes.Length, endmark.Length);
            return result;
        }

        public static bool IsEnd(byte[] data)
        {
            bool result = true;

            if (data.Length >= endmark.Length)
            {
                for (int j = 0; j < endmark.Length; j++)
                {
                    if (data[data.Length - 1 - j] != endmark[endmark.Length - 1 - j])
                    {
                        result = false;
                        break;
                    }
                }
            }

            return result;
        }

        #endregion
    }

    /// <summary>
    /// 客户端
    /// </summary>
    public class Client
    {
        private Encoding encode = Encoding.Default;
        private ManualResetEvent connectDone = new ManualResetEvent(false);
        private ManualResetEvent receiveDone = new ManualResetEvent(false);
        private ManualResetEvent sendDone = new ManualResetEvent(false);
        private static byte[] endmark = new byte[] { 0x3C, 0x45, 0x4F, 0x46, 0x3E }; //约定结束符

        //event
        public delegate void SendCompletedEventHandler(string message);
        public event SendCompletedEventHandler SendCompleted;
        private void OnSendCompleted(string message)
        {
            if (SendCompleted != null)
            {
                SendCompleted(message);
            }
        }

        public void Send(string host, int port, string data)
        {
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //1.建立连接
            clientSocket.BeginConnect(host, port, EndConnect, clientSocket); //异步不能用Connect方法建立连接
            connectDone.WaitOne();

            //2.发送数据
            byte[] sendData = AddEndMark(data);
            clientSocket.BeginSend(sendData, 0, sendData.Length, SocketFlags.None, EndSend, clientSocket);
            //Console.WriteLine("Send:" + data);
            sendDone.WaitOne();

            //3.接收数据
            StateObject state = new StateObject();
            state.workSocket = clientSocket;
            clientSocket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
            receiveDone.WaitOne();

            DestroySocket(clientSocket);
        }

        #region callback methods

        private void EndConnect(IAsyncResult ar)
        {
            Socket socket = (Socket)ar.AsyncState;
            socket.EndConnect(ar);

            connectDone.Set();
        }

        private void EndSend(IAsyncResult ar)
        {
            Socket socket = (Socket)ar.AsyncState;
            socket.EndSend(ar);

            sendDone.Set();
        }

        private void EndReceive(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket socket = state.workSocket;

            int length = socket.EndReceive(ar);
            for (int j = 0; j < length; j++)
            {
                state.data.Add(state.buffer[j]);
            }
            if (!IsEnd(state.data.ToArray()))
            {
                socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
            }
            else
            {
                if (state.data.Count > 0)
                {
                    string receiveData = encode.GetString(state.data.ToArray(), 0, state.data.Count - endmark.Length);
                    //Console.WriteLine("Receive:" + receiveData);
                    OnSendCompleted(receiveData);
                }

                receiveDone.Set();
            }
        }

        #endregion

        #region private methods

        private void DestroySocket(Socket socket)
        {
            if (socket != null)
            {
                if (socket.Connected)
                {
                    socket.Shutdown(SocketShutdown.Both);
                }
                socket.Close();
            }
        }

        private byte[] AddEndMark(string data)
        {
            byte[] databytes = encode.GetBytes(data);
            byte[] result = new byte[databytes.Length + endmark.Length];
            Array.Copy(databytes, 0, result, 0, databytes.Length);
            Array.Copy(endmark, 0, result, databytes.Length, endmark.Length);
            return result;
        }

        private bool IsEnd(byte[] data)
        {
            bool result = true;

            if (data.Length >= endmark.Length)
            {
                for (int j = 0; j < endmark.Length; j++)
                {
                    if (data[data.Length - 1 - j] != endmark[endmark.Length - 1 - j])
                    {
                        result = false;
                        break;
                    }
                }
            }

            return result;
        }

        #endregion
    }
}

重要说明:Receive的ReceiveTimeout对EndReceive不起作用,所以必须是双方约定一个结束符,或者发送方发送完毕立即关闭Socket来结束传输。

运行服务器监听数据:

Server.Listen(8888);

发送和接收TCP数据:

string data = "mzwu.com";
Client client = new Client();
client.SendCompleted += delegate(string message)
{
    Console.WriteLine("Send:{0}\r\nReceive:{1}", data, message);
};
client.Send("127.0.0.1", 8888, data);



参考资料

[1].Socket 类:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket(v=vs.80).aspx
[2].Socket 方法:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket_methods(v=vs.80).aspx
[3].异步客户端套接字示例:http://msdn.microsoft.com/zh-cn/library/bew39x2a(v=vs.80).aspx
[4].异步服务器套接字示例:http://msdn.microsoft.com/zh-cn/library/fx6588te(v=vs.80).aspx

评论: 0 | 引用: 0 | 查看次数: 34596
发表评论
登录后再发表评论!