Wcf Duplex: получить клиентское соединение? - PullRequest
3 голосов
/ 21 октября 2010

Привет
Возможно, это выглядит нелепо, но это проблема по крайней мере для меня

Я написал дуплексный сервис WCF, в моем сервисе мне нужно получить активный клиентский сервис и сохранить его, и когда это произошлоспециальное событие я вызываю конкретного клиента и отправляю некоторые значения для него.Поэтому я определяю словарь и сохраняю клиента в этом.(С помощью этого метода клиент вызывает)

 public static Dictionary<int, IServiceCallbak> ActiveClients;
    public void IConnect(int SenderId)
    {
            if (ActiveClients == null)
                ActiveClients = new Dictionary<int, IServiceCallbak>();
            Client = OperationContext.Current.GetCallbackChannel<IServiceCallbak>();
            if (ActiveClients.Count(ac => ac.Key == SenderId) > 0)
                ActiveClients.Remove(SenderId);
            ActiveClients.Add(SenderId, Client);
    }

Итак, когда мне нужно найти клиента из этого словаря и вызвать конкретный метод: Client.DoSomthing().
Также, когда клиент хочет выйти, он вызывает метод IDisconnectкоторый удалит клиента из словаря.

, поэтому я управляю Active-клиентом в службе !!!

But there is problem in client for managing themselves По истечении периода времени, определенного в app.config, соединение службы будет закрыто, и вы должны обновить его, а затем открытьоказание услуг.

Так что в этом случае:
1) Есть ли какое-либо решение для воссоздания и открытия объекта службы automatically в клиенте.
2) Или когда на стороне сервера, когда служба хочет вызвать клиентов, проверьтесостояние client-service-object из этого словаря и повторное открытие соединения со стороны сервера (Ridiculous-solution)

Edit

Я думаю, что лучшим решением является обработка Suggestion 1, я нене знаю как !!!.
Итак, на данный момент вопрос таков: Is way exist to do Suggestion 1 Or not? Ранее я описываю Предложение 1 в комментарии:
"И автоматически ссылаюсь на событие для этого случая (например, закрытие или прерывание), но я неничего не найдете для этого в Service-Client "

1 Ответ

4 голосов
/ 22 октября 2010

Чтобы предотвратить закрытие соединения на стороне сервера, вы можете настроить метод Heartbeat () в контракте, который клиент может периодически вызывать. Это, однако, не идеально, потому что базовый сокет может упасть, и это ничего не делает для исправления этого.

Что касается вашего предложения 1) если на клиентской стороне вы наследуете от ClientBase, вы несколько застряли в том, что никакие указания на проблему не могут быть даны, пока вы не вызовете метод для маршрутизации в службу. Вам нужно будет обернуть вызов в попытку / перехват, а затем использовать некоторую логику переподключения:

public class MyClass : ClientBase<IContract>, IContract
{
    public void ServiceMethod(String data) {
        try {
            base.Channel.ServiceMethod(data);
        }
        catch (CommunicationException ce) {
            // Perform some reconnect logic here
            base.Channel.ServiceMethod(data);
        }
    }
}

Ваш комментарий к предложению 2) является правильным, если между серверной стороной и клиентом существуют межсетевые экраны, они, скорее всего, не разрешат соединение

Edit: Чтобы расширить мое предложение для 1), вам нужно будет создать новое соединение, когда вызов службы завершится неудачно с CommunicationException. Простейшим подходом было бы создать канал службы в конструкторе, а затем создать другой при сбое вызова:

class ServiceClient {
    Service1Client mService;  // Class generated by VS tool
    public ServiceClient()
        : base() {
            mService = new Service1Client();
    }
    #region IService1 Members
    public string GetData(int value) {
        CommunicationState state = mService.State;
        if (state == CommunicationState.Closed || state == CommunicationState.Faulted) {
            mService = new Service1Client();
        }
        try {
            // Note: The state checked above may not be accurate,
            //  hence the try...catch
            return mService.GetData(value);
        }
        catch (CommunicationException) {
            mService = new Service1Client();  // Reconnect logic
            return mService.GetData(value); // If it fails again we are out of luck...
        }
    }
    #endregion
}

Edit2:

В WCF сеанс обрабатывается клиентом. Если сеанс между клиентом и службой потерян, я не знаю способа восстановить этот сеанс, ни с клиента, ни со службы. Вы, к сожалению, застряли здесь.

Если служба хочет отправить с помощью обратного вызова с прерванным сеансом, проще говоря, она не может. Из-за того, как работают сети, сервис может не знать фактический адрес клиента. Эта и другие проблемы (например, брандмауэры) означают, что попытка восстановить соединение с клиентом из службы просто нецелесообразна. Единственный подход к службе - сохранить данные, которые он хотел отправить клиенту, и отправить их, когда служба обнаружит, что клиент повторно подключился.

Нет никакой гарантии, что клиент будет знать об удалении основного сокета, пока клиент не попытается отправить что-то через сокет, следовательно, попытка ... поймать. Воссоздание канала от клиента, как только он узнает о разорванном соединении, является единственным известным мне способом решения этой проблемы; что делает пример кода.

Идея сердцебиения - это способ активно бороться с нарушенной связью. Его эффективность зависит от ваших требований относительно того, насколько быстро вам нужно обнаружить разорванное соединение и сколько клиентов присутствует. Чем больше клиентов подключено, тем длиннее будет пульс, чтобы вы не загружали сеть в службу.

Edit3:

После некоторого дополнительного копания может быть способ сделать то, что вы хотите автоматически. Вы можете создать так называемый Reliable Session . Активация этого включает создание дополнительных записей в конфигурации:

<netTcpBinding>
    <binding>
        <reliableSession ordered="Boolean"
                    inactivityTimeout="TimeSpan"
                    enabled="Boolean" />
    </binding>
</netTcpBinding>

Он также доступен для привязок, связанных с Http, см. Ссылку на документацию Microsoft по этой функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...