Целевой объект удаленного взаимодействия .NET отказывается от одного вызова — возвращает исключение сокета

У меня есть старое школьное приложение для удаленного взаимодействия .NET, которое мне нужно было немного расширить. В рамках этого я перенес его на .NET 4.0. (ранее был .NET 2.0) Размещенный интерфейс выглядит следующим образом

    public interface IRemoteSupportVM
    {
        string runAnOperation(Customer cust, List<CustomRoute> routes);

        string runAnotherOperation(string customer, string routes);

        string runAThirdOperation(List<string> pathsToBeCleaned);

        string writeFile(string path, string filename, int type, byte[] data);

        string readFile(string path, string filename, out byte[] data);

        string deleteFile(string path, string filename);

        long ping();
    }

ping, readFile, writeFile и deleteFile работают нормально. Когда я вызываю runAnOperation/runAnotherOperation/runAThirdOperation, я немедленно получаю сообщение SocketExcepting, сообщающее мне

Попытка подключения не удалась, потому что подключенная сторона не ответила должным образом через некоторое время, или установленное соединение не удалось, потому что подключенный хост не ответил

Теперь я понимаю, что это куча вздора, потому что все остальные вызовы работают просто отлично, и цель получает вызов и выполняет свою задачу. Но поскольку клиент считает, что вызов не удался, все, что приходит после вызова connect, тоже не работает.

решение имеет множество других интерфейсов удаленного взаимодействия, и, насколько я могу судить, все они работают, кроме этих двух вызовов методов. Есть идеи, что может сбить с толку вызывающего абонента удаленного взаимодействия .NET?

@edit: я заметил еще одну вещь: выполнение операций run * занимает некоторое время. Другие операции возвращаются немедленно. Поскольку у меня есть код обеих сторон интерфейса удаленного взаимодействия, я установил точку останова на реализации ping(), и теперь я также получаю исключение SocketException, когда клиент вызывает ping. Так что, похоже, тайм-аут, о котором я не знаю.


person Stephan Steiner    schedule 20.02.2020    source источник
comment
У вас не может быть двух подключений с одним и тем же IP-адресом источника, IP-адресом назначения и номером порта, поэтому в подключении будет отказано. Из cmd.exe › Netstat -a проверьте состояние соединений и посмотрите, закрывается ли соединение.   -  person jdweng    schedule 20.02.2020
comment
Соединение остается открытым. Сразу после вызова connect() и получения исключения SocketException я могу вызвать ping() на том же прокси-сервере, и он отлично работает.   -  person Stephan Steiner    schedule 20.02.2020
comment
Итак, почему вы открываете соединение, когда оно уже открыто?   -  person jdweng    schedule 20.02.2020
comment
Как сказал @jdweng, у вас может быть только одно активное соединение. Таким образом, вам нужно либо проверить, есть ли у вас уже активное соединение, и пропустить создание нового, если оно есть, либо вам следует избавиться от соединения сразу после его использования и сделать материал потокобезопасным.   -  person Mark-Danney    schedule 20.02.2020
comment
Ааа, теперь я знаю, о чем ты. Название подключения вводит в заблуждение. Он не открывает (сеть/удаленное/tcp) соединение... он говорит удаленному концу что-то сделать. Представьте, что метод называется runSomeAction для ясности. Я собираюсь адаптировать вопрос, чтобы лучше отразить это   -  person Stephan Steiner    schedule 20.02.2020


Ответы (1)


Итак, после мучительного периода проб и ошибок я наконец нашел виновника. Это время ожидания канала при его инициализации. Вот как это было в коде удаленной стороны:

            IDictionary props = new Hashtable
            {
                ["port"] = config.Port,
                ["timeout"] = config.RemotingTimeout,
            };
            var channel = new TcpChannel(props, clientProv, serverProv);

Теперь кажется, что свойство тайм-аута не повлияло на .NET 2.0 - в этом отношении довольно много результатов Google. Тем не менее, в .NET 4.0 это внезапно кажется невозможным. Каждый вызов удаленного взаимодействия обернут IAsync* Begin/EnvInvoke, чтобы гарантировать результат после желаемого тайм-аута (даже если этот результат заключается в том, что сервер не предоставил результат вовремя). Так что либо никто не заметил, что тайм-аут не имеет никакого значения, либо именно по этой причине была установлена ​​​​обертка выполнения (программа была запущена 15 лет назад ... так что кто знает).

Поскольку config.RemotingTimeout был равен 70, вызов должен был завершиться за 70 миллисекунд, иначе я получил бы исключение SocketException. Когда я преобразовал 70 секунд (которые я ожидал) в миллисекунды (так что timeout = 70000), все внезапно начало работать так, как я ожидал.

person Stephan Steiner    schedule 20.02.2020