异步TCP客户端在不同平台上的工作方式不同

时间:2014-12-10 03:32:53

标签: c# windows tcp

我有一个异步的TCP客户端,在Windows xp 32位上工作正常,但在Windows服务器2008和2012 R2 stardard 64位上收到错误消息。不确定为什么它表现不同。

此ServerAddress参数为127.0.0.1。

1:[1]:2014/12/09 22:41:11.224-Connecting to server 127.0.0.1 port 25000
1:[5]:2014/12/09 22:41:11.224-Socket connected to 127.0.0.1:25000
3:[5]:2014/12/09 22:41:11.224-Sent 86 bytes to server.
3:[1]:2014/12/09 22:41:11.115-Thread[0001]: Wait timeout! No response message received.
3:[4]:2014/12/09 22:41:11.303-ReceiveCallback Exception:Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.

代码段:

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

namespace AsynClient
{
    // State object for receiving data from remote device.
    public class StateObject
    {
        // Client socket.
        public Socket workSocket = null;
        // Size of receive buffer.
        public const int BufferSize = 1024;
        // Receive buffer.
        public byte[] buffer = new byte[BufferSize];
        // Received data string.
        public StringBuilder sb = new StringBuilder();
    }

    class AsyncTcpClient
    {
        #region Private Variables

        private Socket client;

        // ManualResetEvent instances signal completion.
        private ManualResetEvent connectDone = new ManualResetEvent(false);
        private ManualResetEvent sendDone = new ManualResetEvent(false);
        private ManualResetEvent receiveDone = new ManualResetEvent(false);

        // The response from the remote device.
        private String response = String.Empty;

        private string address;
        private int port;
        private int timeout;
        private Logger logger;
        private bool bTimeout;

        #endregion

        public bool IsTimeout
        {
            get
            {
                return bTimeout;
            }
            set
            {
                bTimeout = value;
            }
        }

        /// <summary>
        /// Constructor for AsyncTcpClient class
        /// </summary>
        /// <param name="ServerAddress">The TCP/IP server that should be used for connecting</param>
        /// <param name="ServerPort">The TCP/IP port that should be used for connecting</param>
        /// <param name="Timeout">Timeout in seconds</param>
        /// <param name="BaseLogFile">Base log file name</param>
        /// <param name="logSize">Base log file size</param>
        public AsyncTcpClient(string ServerAddress, int ServerPort, int Timeout, string BaseLogFile, long BaseLogSize)
        {
            address = ServerAddress;
            port = ServerPort;
            timeout = Timeout;

            //provide a default log in case the component using this library does not use the logger class
            logger = Logger.GetInstance();
            try
            {
                logger.Initialize(BaseLogFile + (".LOG"), BaseLogSize);
            }
            catch
            {
                //If the init throws an exception that's OK because it means that the top level
                //already initialized the component.
            }
            IsTimeout = false;
        }


        /// <summary>
        /// Connnects to the remote socket server.
        /// </summary>
        public void Connect()
        {
            // Connect to a remote device.
            try
            {
                // Establish the remote endpoint for the socket.
                IPAddress ipAddress = IPAddress.Parse(address); ;
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

                // Create a TCP/IP socket.
                client = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);

                // Connect to the remote endpoint.
                client.BeginConnect(remoteEP,
                    new AsyncCallback(ConnectCallback), client);
                connectDone.WaitOne();
            }
            catch (Exception e)
            {
                client.Disconnect(true);
                connectDone.Reset();

                logger.WriteToLogFile(string.Format("Connect Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
            }
        }

        /// <summary>
        /// Callback function called when a client tries to connect to the server
        /// </summary>
        /// <param name="ar">Represents the status of async result object</param>
        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;

                // Complete the connection.
                client.EndConnect(ar);

                logger.WriteToLogFile(string.Format("Socket connected to {0}", client.RemoteEndPoint.ToString()),
                    MessageType.Information, LogLevel.Basic);

                // Signal that the connection has been made.
                connectDone.Set();
            }
            catch (Exception e)
            {
                logger.WriteToLogFile(string.Format("ConnectCallback Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// Send the data to the TCP server, and wait for signal
        /// </summary>
        /// <param name="client">Represents the TCP server socket</param>
        /// <param name="data">Represents the data</param>
        public void Send(String data)
        {
            try
            {
                // Convert the string data to byte data using ASCII encoding.
                byte[] byteData = Encoding.ASCII.GetBytes(data);

                // Begin sending the data to the remote device.
                client.BeginSend(byteData, 0, byteData.Length, 0,
                    new AsyncCallback(SendCallback), client);

                sendDone.WaitOne();
            }
            catch (Exception e)
            {
                logger.WriteToLogFile(string.Format("Send Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
            }

        }

        /// <summary>
        /// Callback for the send opertaion.
        /// </summary>
        /// <param name="ar">Represents the status of async result object</param>
        public void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device.
                int bytesSent = client.EndSend(ar);

                // Signal that all bytes have been sent.
                sendDone.Set();

                logger.WriteToLogFile(string.Format("Sent {0} bytes to server.", bytesSent), MessageType.Error, LogLevel.Basic);
            }
            catch (Exception e)
            {
                logger.WriteToLogFile(string.Format("SendCallback Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
            }
        }

        /// <summary>
        /// Start listening for incoming data to this connection
        /// </summary>
        public void Receive()
        {
            try
            {
                // Create the state object.
                StateObject state = new StateObject();
                state.workSocket = client;

                // Begin receiving the data from the remote device.
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);

                //wait for the signal or timeout
                bool success = receiveDone.WaitOne(timeout * 1000, false);
                if (!success)
                {
                    IsTimeout = true;
                    logger.WriteToLogFile(string.Format("Thread[{0:d4}]: Wait timeout! No response message received.", Thread.CurrentThread.GetHashCode()), MessageType.Error, LogLevel.Basic);
                }
            }

            catch (Exception e)
            {
                logger.WriteToLogFile(string.Format("Receive Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
            }
        }

        /// <summary>
        /// Callback for the receive operation.
        /// </summary>
        /// <param name="result">Represents the status of async result object</param>
        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the state object and the client socket 
                // from the asynchronous state object.
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;

                if (client.Connected)
                {
                    // Read data from the remote device.
                    int bytesRead = client.EndReceive(ar);

                    if (bytesRead > 0)
                    {
                        // There might be more data, so store the data received so far.
                        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                        // Get the rest of the data.
                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReceiveCallback), state);
                    }
                    else
                    {
                        // All the data has arrived; put it in response.
                        if (state.sb.Length > 1)
                        {
                            response = state.sb.ToString();
                        }

                        // Signal that all bytes have been received.
                        receiveDone.Set();

                        logger.WriteToLogFile(string.Format("Response received:{0}", response), MessageType.Error, LogLevel.Basic);
                    }
                }
            }
            catch (Exception e)
            {
                logger.WriteToLogFile(string.Format("ReceiveCallback Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
            }
        }

        /// <summary>
        /// Stops the TCP Client, closes the socket connection and releases resources.
        /// </summary>
        public void Stop()
        {
            try
            {
                // Release the socket.
                client.Shutdown(SocketShutdown.Both);
                client.Close();

                logger.WriteToLogFile("Close the socket connection and release all the resourses", MessageType.Information, LogLevel.Basic);
            }
            catch (Exception e)
            {
                logger.WriteToLogFile(string.Format("Close Exception:{0}", e.Message), MessageType.Error, LogLevel.Basic);
            }
        }
    }
}

0 个答案:

没有答案