Не удалось установить соединение с TcpListener - PullRequest
1 голос
/ 14 января 2012

Последние 2 недели я пытался решить проблему, по-видимому, безуспешно. У меня есть сервер, использующий класс TcpListener, и клиент, использующий класс TcpClient.

В моих тестах использовалось 2 компьютера во внутренней домашней сети (маршрутизатор 1 уровня). При попытке подключения клиент-компьютер получил исключение "тайм-аут запроса на подключение".

Что я уже пробовал:

  1. Запуск клиента и сервера на одном компьютере - работал
  2. Прослушивание через порт 0.066.0 6666 (проверьте с помощью netstat, что сервер прослушивает)
  3. Отключение клиентских и серверных брандмауэров
  4. Попытка подключить мое удаленное приложение с помощью telnet (чтобы исключить возможность "ошибки кода клиента")
  5. Установка telnet на обоих компьютерах и успешное подключение .

Тем не менее мой сервер, похоже, не подключен. Клиентский компьютер - Windows XP, а серверный компьютер - Windows 7.

Пожалуйста, помогите, я действительно застрял на этом.

Правка - Код сервера ->

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

namespace Utils
{
    public class ClientConnection
{
    public ClientConnection(IPHostEntry hostName, TcpClient client)
    {
        HostName = hostName;
        Client = client;
    }

    public IPHostEntry HostName { get; set; }

    public TcpClient Client { get; set; }
}

public class SocketServer : IDisposable
{

    private const int DefaultRecieveSize = 1024;
    protected const int ReceiveTimeoutBeforeQuiting = 5000;

    private readonly Encoding _defaultEncoding = Encoding.ASCII;
    private readonly TcpListener _socket;

    protected Dictionary<IPAddress, ClientConnection> Clients;
    private static object _locker;

    private readonly AutoResetEvent _listeningStopEvent;
    private readonly Thread _listeningThread;

    private readonly AutoResetEvent _acceptNewClientEvent;

    public delegate void ClientsListChangedEvent();
    public event ClientsListChangedEvent ClientsChangedEvent;

    private Timer _refreshClientsTimer;
    private static int _updateClientListInterval;

    #region Ctors

    protected SocketServer(int port)
    {
        _socket = new TcpListener(IPAddress.Parse("0.0.0.0"),port);
        Clients = new Dictionary<IPAddress, ClientConnection>();

        _updateClientListInterval = Convert.ToInt32(ConfigurationManager.AppSettings["UpdateClientListInterval"]);


        _listeningThread = new Thread(AcceptNewConnections);
        _listeningStopEvent = new AutoResetEvent(false);

        _acceptNewClientEvent = new AutoResetEvent(false);
        _locker = new object();

        _socket.Start();
    }

    #endregion

    #region Send methods

    protected void SendString(IPAddress client, string data)
    {
        // implementation here
    }

    #endregion

    #region Receieve methods

    protected MemoryStream GetInputDataAsMemoryStream(IPAddress client)
    {
        // implementation here    
    }

    protected string GetInputDataAsMemoryString(IPAddress client)
    {
        // implementation here    
    }

    protected string GetInputDataAsMemoryString(IPAddress client, int timeout)
    {
        // implementation here    
    }  

    #endregion

    #region Listening methons

    public void StopListening()
    {
        _listeningStopEvent.Set();

        // todo : check if works
        _refreshClientsTimer.Dispose();
    }

    public bool StartListening()
    {
        if (_listeningThread.ThreadState == ThreadState.Unstarted)
        {
            _listeningThread.Start();

            // start refreshing clients list too. update clients list every 10 seconds
            _refreshClientsTimer = new Timer(UpdateList, null, 0, _updateClientListInterval * 1000);
            return true;
        }
        return false;
    }

    private void AddClientCallback(IAsyncResult ar)
    {
        // get all needed data before entering lock 
        if (_socket != null)
        {
            TcpClient client;
            try
            {
                client = _socket.EndAcceptTcpClient(ar);
            }
            catch (ObjectDisposedException)
            {
                // probebly server has been closed. exit
                return;
            }

            var clientEndPoint = client.Client.RemoteEndPoint;
            var ip = SocketFunctions.ExtractIpFromEndPoint(clientEndPoint);
            IPHostEntry hostName;
            try
            {
                hostName = SocketFunctions.ExtractHostnameFromEndPoint(clientEndPoint);
            }
            catch(SocketException)
            {
                // error while parsing from ip to host name. Put default
                hostName = new IPHostEntry();
            }


            // check if given ip already connected
            if (!Clients.ContainsKey(ip))
            {
                lock (_locker)
                {
                    Clients.Add(ip, new ClientConnection(hostName, client));
                }

                // notify that a new clients has been added
                ClientsChangedEvent.Invoke();
            }
        }
        // a new client has accepted
        _acceptNewClientEvent.Set();
    }

    private void AcceptNewConnections(object obj)
    {
        var shouldStop = false;

        while (!shouldStop)
        {
            _socket.BeginAcceptTcpClient(AddClientCallback, null);

            AutoResetEvent[] events = { _listeningStopEvent, _acceptNewClientEvent };
            var result = WaitHandle.WaitAny(events);

            if (result == 0)
            {
                shouldStop = true;
            }
        }
    }

    #endregion 

    public List<KeyValuePair<string, string>> GetConnectedClients()
    {
        var connectedClients = new List<KeyValuePair<string, string>>();

        lock (_locker)
        {
            foreach (var client in Clients)
            {
                // get only connected clients. Don`t remove - next Timer round will do it anyway and I don`t want to lock _clients
                if (client.Value.Client.Connected)
                {
                    connectedClients.Add(new KeyValuePair<string, string>(client.Key.ToString(), client.Value.HostName.HostName));
                }
            }
        }

        return connectedClients;
    }

    private static void CheckConnectionStatus(TcpClient client)
    {
        if (client.Client.Poll(0, SelectMode.SelectRead))
        {
            var checkConn = new byte[1];
            checkConn[0] = 0;
            try
            {
                if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                {
                    throw new IOException();
                }
            }
            catch (SocketException)
            {
                // for me, both exceptions mean that there was a conncetion error. Throw IOException for this case too
                throw new IOException();
            }
        }
    }

    public void UpdateList(object obj)
    {
        // iterate each client and check its state. Remove if not connected
        var tempClients = new Dictionary<IPAddress, ClientConnection>(Clients);
        var changedOccurred = false;

        lock (_locker)
        {
            foreach (var client in Clients)
            {
                try
                {
                    CheckConnectionStatus(client.Value.Client);
                }
                catch (IOException)
                {
                    // client is not connected anymore
                    tempClients.Remove(client.Key);
                    changedOccurred = true;
                }

            }
        }

        if (changedOccurred)
        {
            lock (_locker)
            {
                Clients = tempClients;
            }

            // notify that a new clients has been added
            ClientsChangedEvent.Invoke();
        }

    }

    #region IDisposble

    public void Dispose()
    {
        if (_socket != null)
        {
            StopListening();
            _socket.Stop();
        }
    }

    #endregion

}

}

...