Search code examples
c#socketsftpcompact-frameworktcplistener

Receive Timeout in Compact Framework 2.0



I've a problem with the sockets in my program. I'm developping an FTP server embedeed in another program and in order to do that I've create a socket and a TCPListener. My problem occures in this case:
- I open the connection for the first time, if nobody connect and I close it, all fine; otherwise if somebody connect to my FTP server all works fine too;
- If, after close the connection the first time and open it again without anybody have been connected before, I get a SocketException of "socket/ip address/port" already in use and I cannot instantiate it again.
The code of my function is that:

    public void Start()
    {
        ServerStarted = true;

        if (this.authHandler == null)
            this.authHandler = new DefaultAuthHandler();

        if (this.fsHandler == null)
            this.fsHandler = new DefaultFileSystemHandler();

        Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        TcpListener listenerServer = new TcpListener(endpoint);
        listenerServer.Start(); // The exception is here at the second time
                                // I open the connection without anybody connected before

        try
        {
            while (ServerStarted)
            {
                socketServer = listenerServer.AcceptSocket();

                try
                {
                    IPEndPoint socketPort = (IPEndPoint)socketServer.RemoteEndPoint;
                    Session session = new Session(socketServer, bufferSize, this.authHandler.Clone(socketPort), this.fsHandler.Clone(socketPort));

                    session.Start();
                    sessions.Add(session);

                    p_HostIPAddress = socketPort.Address;

                    if (p_HostIPAddress != null)
                        HostConnected = true;

                    // Purge old sessions
                    for (int i = sessions.Count - 1; i >= 0; --i)
                    {
                        if (!sessions[i].IsOpen)
                        {
                            sessions.RemoveAt(i);
                            --i;
                        }
                    }
                }
                catch(Exception ex)
                {
                }
            }
        }
        catch (SocketException socketEx)
        {
        }
        finally
        {
            foreach (Session s in sessions)
            {
                s.Stop();
                HostConnected = false;
            }
            TcpSocketListener = null;
        }
    }

I know that in Compact framework there aren't the Timeout calls and so, what can I do to avoid that my socket still open in background. Ohw, right, another extra info:
my ftp server actually use the OpenNETCF FTP library


Solution

  • Ok, I've solved using the SetSocketOption and I've changed a bit the code. Here is it now:

        public void Start()
        {
            ServerStarted = true;
    
            if (this.authHandler == null)
                this.authHandler = new DefaultAuthHandler();
    
            if (this.fsHandler == null)
                this.fsHandler = new DefaultFileSystemHandler();
    
            socketServer = new Socket(AddressFamily.InterNetwork,
                                      SocketType.Stream, 
                                      ProtocolType.Tcp);
    
            /* Here is the change. In this way I can reuse multiple times the
             * same address without getting the SocketException.*/
            socketServer.SetSocketOption(SocketOptionLevel.Socket,
                                         SocketOptionName.ReuseAddress, 
                                         1);
    
            Socket handler = null;
    
            try
            {
                socketServer.Bind(endpoint);
                socketServer.Listen(10);
    
                while (ServerStarted)
                {
                   handler = socketServer.Accept();
    
                    try
                    {
                        IPEndPoint socketPort = (IPEndPoint)handler.RemoteEndPoint;
                        Session session = new Session(handler,bufferSize, 
                                             this.authHandler.Clone(socketPort),
                                             this.fsHandler.Clone(socketPort));
    
                        session.Start();
                        sessions.Add(session);
    
                        p_HostIPAddress = socketPort.Address;
    
                        if (p_HostIPAddress != null)
                            HostConnected = true;
    
                        // Purge old sessions
                        for (int i = sessions.Count - 1; i >= 0; --i)
                        {
                            if (!sessions[i].IsOpen)
                            {
                                sessions.RemoveAt(i);
                                --i;
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                    }
                }
            }
            catch (SocketException socketEx)
            {
            }
            finally
            {
                handler.Close();
    
                foreach (Session s in sessions)
                {
                    s.Stop();
                    HostConnected = false;
                }
            }
        }