很抱歉再次发布同样的问题,但种类没有第一次正确。 :)
这是服务器应用程序的代码,它可以接收连接并应该向客户端发送消息。
正如您所看到的,我有GUI的“类Form1:Form ”和服务器功能的“类ServerWCallbackImpl:IServerWithCallback ”。
问题是这些类无法通信,即我不能从表单事件中引入服务器函数,例如buttonClick,也不能在表单中更改某些内容,比如TextBox1.Text + = .. 。,来自服务器功能。
也许有人可以解释一下,代码应该怎么样,以便它可以工作?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
namespace server
{
[ServiceContract(Namespace = "server", CallbackContract = typeof(IDataOutputCallback), SessionMode = SessionMode.Required)]
public interface IServerWithCallback ///// what comes from the client to the server.
{
[OperationContract(IsOneWay = true)]
void StartConnection(string clientName);
[OperationContract(IsOneWay = true)]
void Message_Cleint2Server(string msg);
}
public interface IDataOutputCallback ///// what goes from the sertver, to the client.
{
[OperationContract(IsOneWay = true)]
void AcceptConnection();
[OperationContract(IsOneWay = true)]
void Message_Server2Client(string msg);
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) /// once the form loads, create and open a new ServiceEndpoint.
{
ServiceHost duplex = new ServiceHost(typeof(ServerWCallbackImpl));
duplex.AddServiceEndpoint(typeof(IServerWithCallback), new NetTcpBinding(), "net.tcp://localhost:9080/service");
duplex.Open();
this.Text = "SERVER *on-line*";
}
private void buttonSendMsg_Click(object sender, EventArgs e)
{
/// callback.Message_Server2Client(textBox2.Text);
/// The name 'Message_Server2Client' does not exist in the current context :(
}
}
class ServerWCallbackImpl : IServerWithCallback /// NEED TO SOMEHOW MERGE THIS ONE WITH THE FORM1 CLASS
{
IDataOutputCallback callback = OperationContext.Current.GetCallbackChannel<IDataOutputCallback>();
public void StartConnection(string name)
{
/// TextBox1.text += name + " has connected!";
/// 'TextBox1' does not exist in the current context :(
/// can't reach form1 components. :/
MessageBox.Show( name + " has connected!");
Message2Client("Welcome, "+name+"!");
}
public void Message_Cleint2Server(string msg)
{
/// TextBox1.text += msg;
/// 'TextBox1' does not exist in the current context :(
/// can't reach form1 components. :/
}
public void Message2Client(string msg)
{
callback.Message_Server2Client(msg);
}
}
}
答案 0 :(得分:1)
双工变量的生命周期仅限于Form1_Load方法。这意味着您的主机将在方法完成后终止。要保持主机运行,请在方法外声明双工变量,并在方法中实例化它。
像这样:
public partial class Form1 : Form {
//Declare the variable in the class, not the method body
private ServiceHost duplex;
public Form1() {
InitializeComponent();
}
// once the form loads open a new ServiceEndpoint.
private void Form1_Load(object sender, EventArgs e) {
duplex = new ServiceHost(typeof(ServerWCallbackImpl));
duplex.AddServiceEndpoint(typeof(IServerWithCallback), new NetTcpBinding(), "net.tcp://localhost:9080/service");
duplex.Open();
this.Text = "SERVER *on-line*";
}
private void buttonSendMsg_Click(object sender, EventArgs e) {
/// callback.Message_Server2Client(textBox2.Text);
/// The name 'Message_Server2Client' does not exist in the current context :(
}
}
EDIT1:
如果使用类似示例的类型实例化ServiceHost,则将为每个连接创建该类型的实例。您可以将实例的生命周期设置为我认为的会话,呼叫或连接。我不确定该对象如何访问您的表单。但是,如果您自己实例化ServerWCallbackImpl类并将引用传递给将要使用该实例的主机。
public partial class Form1 : Form {
//Declare the variable in the class, not the method body
private ServiceHost duplex;
private ServerWithCallbackImpl localInstance;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
localInstance = new ServerWithCallbackImpl();
NetTcpBinding binding = new NetTcpBinding ();
duplex = new ServiceHost(localInstance, new Uri[] { new Uri("net.tcp://localhost:9080") });
duplex .AddServiceEndpoint(typeof(IServerWithCallback), binding, "service");
duplex .Open();
this.Text = "SERVER *on-line*";
}
}
然后,ServerWithCallbackImpl对象必须跟踪它的客户端。要让服务器更新GUI,您可能希望将对Form作为参数的引用传递给ServerWithCallbackImpl构造函数。请查看the Publish/Subscriber pattern以更深入地了解回调。