服务器信道地址是 http://localhost:18001/ETmedia客户端 程序Form1 创建 4个 ClientForm
每个ClientForm都向服务器信道地址是 http://localhost:18001/ETmedia注册第一个注册成功,其它的就会报“信道 'http' 已注册。”(RemotingException) 如何实现一个服务器端server.exe和一个Form1.exe里的多个clientForm向同一个信道注册
每个ClientForm都向服务器信道地址是 http://localhost:18001/ETmedia注册第一个注册成功,其它的就会报“信道 'http' 已注册。”(RemotingException) 如何实现一个服务器端server.exe和一个Form1.exe里的多个clientForm向同一个信道注册
信道名称在应用程序域中必须是唯一的
在注册不同信道的时候,显式指定其信道名称
IChannel channel1 = new TcpClientChannel( "Channel1", new BinaryClientFormatterSinkProvider() );
ChannelServices.RegisterChannel( channel1, true );
IChannel channel2 = new TcpClientChannel( "Channel2", new BinaryClientFormatterSinkProvider() );
ChannelServices.RegisterChannel( channel2, true );
参考
{
for (int i = 0; i < 2; i++)
{
ETMPlayer xplayer = new ETMPlayer();
xplayer.playerid = i;
xplayer.Show();
}
}using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using ETMedia.Communication;
using System.Net.Sockets;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting;
using System.Collections;namespace ETMedia.XPlayers
{
public partial class ETMPlayer : Form
{
public ETMPlayer()
{
InitializeComponent();
}
public int playerid=0;
private void ETMPlayer_Load(object sender, EventArgs e)
{
MethodInvoker mi = new MethodInvoker(InitializeModule);
mi.Invoke();
}
private void ETMPlayer_FormClosed(object sender, FormClosedEventArgs e)
{
if (channel != null)
{
ChannelServices.UnregisterChannel(channel);
}
GC.Collect();
}
private void buttonSend_Click(object sender, EventArgs e)
{
byte[] data = Encoding.Default.GetBytes("你好");
}
#region Remoting HttpChannel channel; private void InitializeModule()
{
//---------------------------------------------------------------------------------------------------
if (RegisterChannel(10081 , 18001 , "localhost", "ETMPlayer" + playerid))
{
MessageBox.Show("ETMPlayer 已注册到 SERVER", @"成功 ETMPlayer" + playerid); }
//---------------------------------------------------------------------------------------------------
}
#region Player Client注册到Agent
/// <summary>
/// Player Client注册到Agent,这里要用一个线程循环注册,如果注册不成功要catch异常,继续直到注册成功
/// </summary>
/// <param name="playerport">10081</param>
/// <param name="agentport">18001</param>
/// <param name="agentip">localhost</param>
/// <param name="identifier"> "DMP.Remoting.Agent"</param>
public bool RegisterChannel(int playerport, int agentport, string agentip, string identifier)
{
bool isReg = false;
while (!isReg)
{
try
{
// creates a client object that 'lives' here on the client.
// this object lives here on the client
//_CallbackSink = new CallbackSink();
// hook into the event exposed on the Sink object so we can transfer a server
// message through to this class.
//_CallbackSink.OnHostToClient += new delCommsInfo(CallbackSink_OnHostToClient);
//_CallbackSink.OnAgentToPlayer += new dealInternalMessageInfo(_CallbackSink_OnAgentToPlayer);
// Register a client channel so the server can communicate back - it needs a channel
// opened for the callback to the CallbackSink object that is anchored on the client!
SoapClientFormatterSinkProvider clientFormatter = new SoapClientFormatterSinkProvider();
Hashtable ht = new Hashtable();
ht["name"] = identifier;
ht["port"] = playerport; channel = new HttpChannel(ht, clientFormatter,null);
ChannelServices.RegisterChannel(channel, false);
// now create a transparent proxy to the server component
string url= @"http://" + agentip + ":" + agentport + "/" + identifier;
RemoteServiceObject obj = (RemoteServiceObject)Activator.GetObject(typeof(RemoteServiceObject), url);
//if (obj == null) continue;
// Register ourselves to the server with a callback to the client sink.
obj.ReceiveFromServer += new DataReceiveHandler(ReceiveFromServerProcess);/////《----------------加了这句就报已被注册了,为什么
//_ServerTalk.RegisterAgentToPlayer(dmpPlayer, new dealInternalMessageInfo(_CallbackSink.HandleToPlayer)); isReg = true;
}
catch (RemotingException rmt) {
isReg = false;
System.Diagnostics.Trace.WriteLine(rmt);
System.Threading.Thread.Sleep(3000);
continue;
}
catch (SocketException se)
{
isReg = false;
if (se.SocketErrorCode == SocketError.AddressAlreadyInUse)
{
System.Diagnostics.Trace.WriteLine(@"Client playerport=" + playerport+"+1");
playerport = playerport + 1;
}
continue;
}
catch (Exception x)
{
isReg = false;
//_CallbackSink = null;
//_ServerTalk = null;
System.Diagnostics.Trace.WriteLine(x);
System.Threading.Thread.Sleep(3000);
continue;
}
}
return isReg;
} void ReceiveFromServerProcess(object sender, ReceiveDataEventArgs e)
{
MessageBox.Show("ETMPlayer ReceiveFromServerProcess" + e.Data,@"ETMPlayer"+playerid);
}
#endregion
#endregion
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ETMedia.Communication;
using System.Threading;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting;
using System.Collections;
using System.Net.Sockets;namespace ETMedia.Remote
{
public partial class FormRemote : Form
{
public FormRemote()
{
InitializeComponent();
} private void FormRemote_Load(object sender, EventArgs e)
{
MethodInvoker mi = new MethodInvoker(InitializeModule);
mi.Invoke();
}
private void FormRemote_FormClosed(object sender, FormClosedEventArgs e)
{
if (http_channel != null)
{
ChannelServices.UnregisterChannel(http_channel);
}
}
//Dictionary <string ,>
#region Remoting 内部通信的方法 HttpChannel http_channel; private void InitializeModule()
{
//--------------------------------------------------------------------------------------------------- //for (int i = 0; i < 10; i++)
//{
// string name = @"ETMPlayer" + i;
// int port = 18001 + i;
// if (RegisterChannel(port,name))
// {
// System.Diagnostics.Trace.WriteLine(name + @" SERVER注册成功 @" + port);
// }
//} string name = @"ETMPlayer";
int port = 18001;
if (RegisterChannel(port, name))
{
System.Diagnostics.Trace.WriteLine(name + @" SERVER注册成功 @" + port);
}
//---------------------------------------------------------------------------------------------------
}
#region 注册服务
public bool RegisterChannel(int port, string identifier)
{
bool isReg = false;
while (!isReg)
{
try
{
// Set the TypeFilterLevel to Full since callbacks require additional security requirements
SoapServerFormatterSinkProvider serverFormatter = new SoapServerFormatterSinkProvider();
serverFormatter.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
// we have to change the name since we can't have two channels with the same name.
Hashtable ht = new Hashtable();
ht["name"] = identifier;
ht["port"] = port;// 9000;
// now create and register our custom HttpChannel
http_channel = new HttpChannel(ht, null, serverFormatter);
ChannelServices.RegisterChannel(http_channel, false);
//// register a WKO type in Singleton mode
RemotingConfiguration.RegisterWellKnownServiceType(new WellKnownServiceTypeEntry(
typeof(RemoteServiceObject),
identifier,
WellKnownObjectMode.SingleCall //
));
isReg = true;
}
catch (Exception x)
{
isReg = false;
if (x is SocketException)
{
SocketException se = (SocketException)x;
if (se.SocketErrorCode == SocketError.AddressAlreadyInUse)
{
System.Diagnostics.Trace.WriteLine(@"Server port=" + port + "+1");
port = port + 1;
}
}
System.Threading.Thread.Sleep(3000);
continue;
}
}
return isReg;
}
#endregion #endregion private void btn_etmply_Play_Click(object sender, EventArgs e)
{
byte[] data = Encoding.Default.GetBytes("Play");
} }
}
//远程对象
public delegate void DataReceiveHandler(object sender, ReceiveDataEventArgs e);
public class RemoteServiceObject : MarshalByRefObject
{ public RemoteServiceObject() { }
public event DataReceiveHandler ReceiveFromServer;
public void OnReceiveFromServer(object sender, ReceiveDataEventArgs e)
{
if (this.ReceiveFromServer != null)
{
ReceiveFromServer(this, e);
}
}
} [Serializable]
public class ReceiveDataEventArgs : EventArgs
{
private string rec_data; public string Data
{
get { return rec_data; }
set { rec_data = value; }
} }
但是我感觉这个错误就是因为你重复注册信道的问题,你可以每次使用完信道后,用ChannelServices.UnregisterChannel注销信道