클라이언트에 이벤트를 발생 시키려면 WCF 서비스가 필요합니다. 그 콜백 채널을 통해 발생 읽었습니다, 나는 다음과 같은 방식으로 그것을 구현했습니다 : 서비스 인터페이스 :ChannelFactory를 통해 생성 된 WCF 서비스에서 콜백 채널을 설정하는 방법은 무엇입니까?
public interface IServiceCallback
{
[OperationContract(IsOneWay = true)]
void OnNewAlert(Alert a);
[OperationContract(IsOneWay = true)]
void OnProductEdited(Product p);
[OperationContract(IsOneWay = true)]
void OnHighlightChanged(Dictionary<User, List<Product>> highlighted);
[OperationContract(IsOneWay = true)]
void OnCatalogUpdated();
event EventHandler NewAlert;
event EventHandler ProductEdited;
event EventHandler HighlightChanged;
event EventHandler CatalogUpdated;
}
[ServiceContract(CallbackContract = typeof(IServiceCallback))]
public interface IService : IDisposable
{
[OperationContract]
List<Product> GetProducts(Predicate<Product> match = null, int limit = 0, string username = null);
[OperationContract]
Product GetProduct(Predicate<Product> match, string username = null);
[OperationContract]
Product GetRandomProduct(Predicate<Product> match = null, string username = null);
[OperationContract]
int GetFlagIndex(string flagName);
[OperationContract]
void SetFlag(string pid, string flagName, bool value);
[OperationContract]
List<Alert> GetAlerts(string username);
[OperationContract]
void DismissAlert(Alert alert, String username);
[OperationContract]
void HighlightProduct(List<string> pids, string user);
[OperationContract]
void EditProduct(string pid, Dictionary<string, object> fieldValues, string username = null);
[OperationContract]
void AttachModule(IModule m);
[OperationContract]
void Ping();
event EventHandler NewAlert;
event EventHandler ProductEdited;
event EventHandler HighlightChanged;
event EventHandler CatalogUpdated;
}
서비스 구현 : 클라이언트에
namespace Service
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class ServiceInstance : IService
{
List<IServiceCallback> callbackChannels = new List<IServiceCallback>();
//other vars
public ServiceInstance()
{
//lots of stuff here
}
private User SignalUser(string username)
{
if (username == null)
return null;
IServiceCallback channel = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
if (!callbackChannels.Contains(channel)) //if CallbackChannels not contain current one.
{
callbackChannels.Add(channel);
}
User user = knownUsers.Find(p => p.username == username);
if (user == null)
{
user = new User();
user.username = username;
user.highlighColor = Color.FromArgb(r.Next(0, 128), r.Next(0, 128), r.Next(0, 128));
knownUsers.Add(user);
foreach (KeyValuePair<Alert, List<User>> kvp in alerts)
{
kvp.Value.Add(user);
}
}
user.lastOnline = DateTime.Now;
if(!onlineUsers.Contains(user))
onlineUsers.Add(user);
return user;
}
//lots of other things here
}
}
콜백 구현 :
를class ServiceEventHandler : IServiceCallback
{
public event EventHandler NewAlert;
public event EventHandler ProductEdited;
public event EventHandler HighlightChanged;
public event EventHandler CatalogUpdated;
public void OnCatalogUpdated()
{
CatalogUpdated?.BeginInvoke(null, null, null, null);
}
public void OnHighlightChanged(Dictionary<User, List<Product>> highlighted)
{
HighlightChanged?.BeginInvoke(highlighted, EventArgs.Empty, null, null);
}
public void OnNewAlert(Alert a)
{
NewAlert?.BeginInvoke(a, EventArgs.Empty, null, null);
}
public void OnProductEdited(Product p)
{
ProductEdited?.BeginInvoke(p, EventArgs.Empty, null, null);
}
}
여기 내 문제가 있습니다. 클라이언트 쪽에서는 이 StackOverflow의 응답에 따라
EventHandler eventHandler = new EventHandler();
MyServiceClient client = new MyServiceClient(new InstanceContext(eventHandler));
:이 같은 서비스에 전달하기로 https://stackoverflow.com/a/1143777/2018696
하지만 내 클라이언트 구현에 대해 알고하지 않기 때문에 나는이 같은 내 서비스에 연결하지 마십시오 서비스의, 그것은 단지 2 개의 공용 영역을 알고있다! 그래서 나는 다음과 같이 연결합니다
public static IService GetService(string serviceAddress)
{
Uri service_uri = new Uri(serviceAddress);
var endpoint = new EndpointAddress(service_uri, new[] { AddressHeader.CreateAddressHeader(settings["username"], "", "") });
IService service = ChannelFactory<IService>.CreateChannel(new BasicHttpBinding(), endpoint);
return service;
}
그래서 어떻게 콜백이 작동하려면 어떻게해야합니까?
업데이트 : 코멘트에 의해 제안 된대로, 내가 WsDualHTTPBinding와 DuplexChannelFactory과은 BasicHttpBinding으로 ChannelFactory에 교체, 그리고 서버에서 응답을받지 않도록,
좋아. 콜백 처리기를 긁으면 BasicHTTPBinding 응답을 얻습니다. 그래서 본질적 :
[ServiceContract]
BasicHttpBinding();
ChannelFactory<IService>.CreateChannel(binding, endpoint);
이 ^이
[ServiceContract(CallbackContract = typeof(IServiceCallback))]
WSDualHttpBinding(WSDualHttpSecurityMode.None);
DuplexChannelFactory<IService>.CreateChannel(new InstanceContext(handler), binding, endpoint);
^작동이되지 않습니다.
로컬 호스트에서는 작동하지만 LAN이나 인터넷에서는 작동하지 않습니다. 방화벽은 서버와 클라이언트 모두에서 꺼져 있습니다. 서버에 접속하려고 할 때 60 초 제한 시간이 있습니다.
진행 방향을 알려주는 [DuplexChannelFactory 클래스] (https://msdn.microsoft.com/en-us/library/ms576164(v=vs.110) .aspx)를 살펴보십시오. . – carlosfigueira
@carlosfigueira 감사합니다. 저는 약간의 변경을가했지만, 지금은 서비스에서 응답을 얻지 못했습니다. "업데이트"를보십시오. 감사! – Daniel