Я разрабатываю клиент-серверное приложение для чата (на самом деле это не так, но давайте представим, что я :)), и я немного озадачен некоторыми условиями гонки, с которыми я столкнулся.
Допустим, у меня есть следующий код:
public interface IServer
{
[OperationContract(IsOneWay = false)]
[FaultContract(typeof(ChatException))]
void BroadcastMessage(string msg);
}
public class Server : IServer
{
void BroadcastMessage(string msg) // I'm not mentionning the try/catch/throw FaultException here for readability purposes
{
foreach (IClientCallback c in callbacks){
c.ReceiveMessage(msg);
}
}
}
public interface IClientCallback
{
[OperationContract(IsOneWay = true)]
void ReceiveMessage(string s);
}
А вот выдержка из конфигурации переплета:
<endpoint address=""
binding="netTcpBinding"
bindingConfiguration="DuplexBinding"
contract="IServer" />
<binding name="DuplexBinding" sendTimeout="00:01:00">
<reliableSession ordered="true" inactivityTimeout="00:05:00" enabled="true"/>
<security mode="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
Это, конечно, своего рода псевдо-c #, для ясности я удалил много неуместного кода.
Теперь к вопросу:
Этот код не будет работать. Когда я вызываю BroadcastMessage, метод никогда не возвращается, и я в итоге получаю тайм-аут на стороне клиента. Если я выполняю отладку на стороне сервера, все выглядит нормально (я возвращаюсь из метода BroadcastMessage в точности так, как можно было бы ожидать, и я не блокирую ни один из односторонних вызовов ReceiveMessage)
Вот два способа исправить этот код:
- удалить FaultContract и объявить метод BroadcastMessage как oneway = true
- Передача сообщения всем, НО начальный отправитель
Моим первым предположением было то, что клиентская сторона ожидала возврата сервера и, таким образом, была недоступна для обработки входящего вызова ReceiveMessage с сервера, блокируя таким образом сервер, НО ReceiveMessage объявляется как односторонний и отлаживает сервер показывает, что он не блокирует ни один вызов ReceiveMessage
Теперь мои вопросы:
Что происходит?
Есть ли другие способы исправить это? (может быть, путем настройки конфигурации привязки?)
Допустим, я выбрал исправление 2 (т. Е. Не транслировать обратно отправителю), что произойдет, если сервер вызовет мой обратный вызов ReceiveMessage (потому что кто-то еще отправил мне сообщение), пока я жду своего собственного Вызов BroadcastMessage завершен?
Я читал, что вызовы OneWay не полностью односторонние, и что сервер все еще ожидает HTTP-ответа от другой стороны. Есть какие-нибудь подробности по этому поводу? в частности, может ли клиент отвечать на такие ответы http, когда он заблокирован при удаленном вызове?
Редактировать: Консоль .net 3.5 на стороне сервера, Winforms .net 3.5 на стороне клиента