views:

30

answers:

0

I have a TCP client/server application. 1) server is listening on a port 2) client send request and server accept the connection 3) send receive operation performed 4) server tries to disconnect the connection (first Shutdown then Close) 5) connection state changed to TIME_WAIT 6) the next time client open another socket but sending does not completed successfully (it send 400 byte and server receive 330 byte)

What's wrong with this scenario ? I think there is something with the previous connection that does not closed successfully what can i do to forcibly close the previous connection


using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace SocketAsyncServer
{
    internal sealed class SocketListener
    {
        private BufferManager bufferManager;
        private Socket listenSocket;
        private static Mutex mutex = new Mutex();
        private Int32 numConnectedSockets;
        private Int32 numConnections;
        private const Int32 opsToPreAlloc = 2;
        private SocketAsyncEventArgsPool readWritePool;
        private Semaphore semaphoreAcceptedClients;
        public delegate void OnReceiveCompleted(object receivedObject, SocketAsyncEventArgs e);
        public event OnReceiveCompleted ReceivedComplete;
        internal SocketListener(int numConnections, int receiveBufferSize)
        {
            this.numConnectedSockets = 0;
            this.numConnections = numConnections;
            this.bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToPreAlloc,
                receiveBufferSize);

            this.readWritePool = new SocketAsyncEventArgsPool(numConnections);
            this.semaphoreAcceptedClients = new Semaphore(numConnections, numConnections);
        }

        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            Socket s = e.AcceptSocket;
            try
            {
                s.Shutdown(SocketShutdown.Both);
            }
            catch (Exception ex)
            {
                string errorMessage = ex.Message;
                // Throws if client process has already closed.
            }
            s.Close();
            s = null;

            // Decrement the counter keeping track of the total number of clients connected to the server.
            this.semaphoreAcceptedClients.Release();
            Interlocked.Decrement(ref this.numConnectedSockets);

            // Free the SocketAsyncEventArg so they can be reused by another client.
            this.readWritePool.Push(e);
        }

        internal void Init()
        {
            this.bufferManager.InitBuffer();
            SocketAsyncEventArgs readWriteEventArg;

            for (int i = 0; i (OnIOCompleted);
                this.bufferManager.SetBuffer(readWriteEventArg);
                this.readWritePool.Push(readWriteEventArg);
            }
        }

        /// 
        /// Callback method associated with Socket.AcceptAsync 
        /// operations and is invoked when an accept operation is complete.
        /// 
        /// Object who raised the event.
        /// SocketAsyncEventArg associated with the completed accept operation.
        private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
        {
            this.ProcessAccept(e);
        }

        /// 
        /// Callback called whenever a receive or send operation is completed on a socket.
        /// 
        /// Object who raised the event.
        /// SocketAsyncEventArg associated with the completed send/receive operation.
        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");
            }
        }

        private void ProcessSend(SocketAsyncEventArgs e)
        {
            CloseClientSocket(e);
        }

        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            SocketAsyncEventArgs readEventArgs = this.readWritePool.Pop();
            readEventArgs.AcceptSocket = e.AcceptSocket;

            string endPointAddress = ((IPEndPoint)e.AcceptSocket.RemoteEndPoint).Address.ToString();
            if (endPointAddress == "::ffff:127.0.0.1")
            {
                CloseClientSocket(e);
            }
            else
            {
                // As soon as the client is connected, post a receive to the connection.
                bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
                if (!willRaiseEvent)
                    this.ProcessReceive(readEventArgs);
            }
            // Accept the next connection request.
            this.StartAccept(e);
        }

        /// 
        /// 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.
        /// 
        /// SocketAsyncEventArg associated with the completed receive operation.
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            // Check if the remote host closed the connection.
            if (e.BytesTransferred > 0)
            {
                if (e.SocketError == SocketError.Success)
                {
                    Int32 bytesTransferred = e.BytesTransferred;

                    MemoryStream memStream = new MemoryStream();
                    memStream.Write(e.Buffer, e.Offset, bytesTransferred);
                    memStream.Position = 0;
                    BinaryFormatter formatter = new BinaryFormatter();
                    try
                    {
                        object receivedObj = formatter.Deserialize(memStream);
                        if (ReceivedComplete != null)
                            ReceivedComplete(receivedObj, e);
                    }
                    catch (SerializationException ex) { }
                }
            }
        }

        public void SendResponse(SocketAsyncEventArgs e, string message)
        {
            Socket s = e.AcceptSocket;
            byte[] messageBytes = Encoding.ASCII.GetBytes(message);
            e.SetBuffer(messageBytes, 0, messageBytes.Length);
            bool willRaiseEvent = s.SendAsync(e);
            if (!willRaiseEvent)
                this.ProcessSend(e);
        }

        internal void Start(int listeningPort)
        {
            IPAddress[] addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;
            IPEndPoint localEndPoint = new IPEndPoint(addressList[addressList.Length - 1], listeningPort);
            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
            {
                listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
                listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
            }
            else
                listenSocket.Bind(localEndPoint);

            listenSocket.Listen(1);
            StartAccept(null);

            mutex.WaitOne();
        }

        private void StartAccept(SocketAsyncEventArgs acceptEventArg)
        {
            if (acceptEventArg == null)
            {
                acceptEventArg = new SocketAsyncEventArgs();
                acceptEventArg.Completed += new EventHandler(OnAcceptCompleted);
            }
            else
            {
                // Socket must be cleared since the context object is being reused.
                acceptEventArg.AcceptSocket = null;
            }

            this.semaphoreAcceptedClients.WaitOne();
            bool willRaiseEvent = this.listenSocket.AcceptAsync(acceptEventArg);
            if (!willRaiseEvent)
                this.ProcessAccept(acceptEventArg);
        }

        internal void Stop()
        {
            mutex.ReleaseMutex();
        }
    }
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Common;
namespace SocketAsyncClient
{
    /// 
    /// Implements the connection logic for the socket client.
    /// 
    internal sealed class SocketClient : IDisposable
    {
        private Socket clientSocket;
        private bool connected = false;
        private IPEndPoint hostEndPoint;


        internal SocketClient(string hostName, int port)
        {
            IPHostEntry host = Dns.GetHostEntry(hostName);
            IPAddress[] addressList = host.AddressList;

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

        public void Connect()
        {
            try
            {
                clientSocket.Connect(hostEndPoint);
            }
            catch (Exception ex)
            {
                // Connection failed
            }
        }

        public string SendSearchRequest(FilterObject filter)
        {
            if (clientSocket.Connected)
            {
                MemoryStream memStream = new MemoryStream();
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(memStream, filter);

                // Create a buffer to send.
                byte[] sendBuffer = memStream.ToArray();
                int byteSent = clientSocket.Send(sendBuffer);
                byte[] receivedBuffer = new byte[4096];
                int bytesReceived = clientSocket.Receive(receivedBuffer);
                string message = Encoding.ASCII.GetString(receivedBuffer, 0, bytesReceived);
                if (clientSocket.Connected)
                {
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Close();
                }
                return message;
            }
            else
            {
                return "";
            }
        }


        public void Dispose()
        {
            if (this.clientSocket.Connected)
                this.clientSocket.Close();
        }
    }
}