.net 원격으로 몇 가지 테스트를 수행하고 있으며 위임을 사용하는 동안 문제가 있음을 발견했습니다.
서버 및 클라이언트 자체 인 단일 앱이 있습니다. 사용자가 탐색기에서 앱을 처음 실행하면 서버로 실행되고 클라이언트로 새 프로세스를 시작합니다. 둘 다 잘 작동합니다. 이제 사용자가 서버와 클라이언트 프로세스가 여전히 실행 중일 때 다시 실행하면 클라이언트가되어 새로운 프로세스가 시작되었다는 메시지를 서버에 보낸 다음 자체적으로 종료된다고 가정합니다.
대리인이 클라이언트 대신 서버 프로세스에서 실행되는 것을 제외하고는 모두 잘 작동합니다.
다음은 코드입니다.
const string PIPE_NAME = "testPipeName33";
const string OBJECT_NAME = "test";
static RemoteObject remoteObject;
static void RegisterClient()
{
IpcClientChannel chan = new IpcClientChannel();
ChannelServices.RegisterChannel(chan, false);
remoteObject = (RemoteObject)Activator.GetObject(typeof(RemoteObject),
string.Format("ipc://{0}/{1}", PIPE_NAME, OBJECT_NAME));
}
static void RegisterServer()
{
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
IpcServerChannel chan = new IpcServerChannel("", PIPE_NAME, serverProvider);
ChannelServices.RegisterChannel(chan, false);
RemotingServices.Marshal(new RemoteObject(), OBJECT_NAME);
}
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if ((args.Length == 0 || args[0] == "s"))
{
try
{
RegisterServer();
}
catch (RemotingException)
{
// try to register it with the pipe name. If it fails, means server is already running.
//bad idea, I know, but it's just for barebone quick test
RegisterClient();
remoteObject.OnNewProcessStarted("test");
Application.Exit();
return;
}
Process.Start(Application.ExecutablePath, "c");
Application.Run(new Form1("Server"));
}
else
{
IsClient = true;
RegisterClient();
remoteObject.SetOnNewProcessStarted(OnNewProcessStarted);
Application.Run(new Form1("Client"));
}
}
static bool IsClient = false;
static bool OnNewProcessStarted(string commandLine)
{
MessageBox.Show("Is Client : " + IsClient);//problem here, IsClient should be true
return true;
}
RemoteObject 클래스.
public delegate bool OnNewProcessStartedDelegate(string text);
internal class RemoteObject : MarshalByRefObject
{
public OnNewProcessStartedDelegate OnNewProcessStartedHandler;
public bool OnNewProcessStarted(string commandLine)
{
if (OnNewProcessStartedHandler != null)
return OnNewProcessStartedHandler(commandLine);
return false;
}
public void SetOnNewProcessStarted(OnNewProcessStartedDelegate onNewProcessStarted)
{
OnNewProcessStartedHandler = onNewProcessStarted;
}
public override object InitializeLifetimeService()
{
return null;
}
}
추신 : 하나의 서버와 하나의 클라이언트 만있을 수 있습니다.
새 클라이언트가 서버에서 RemoteObject의 델리게이트를 호출하기 때문에 Delegate가 서버에서 실행 중입니다. 서버와 첫 번째 클라이언트 사이에 등록 된 콜백이 없습니다. 요청을 수신하는 첫 번째 클라이언트에 아무도 없기 때문에 서버는 콜백 할 프로세스를 알지 못합니다. 일반적으로 WCF와 같은 기술을 사용하면 이중 통신을 허용하는 DualHttpBindings를 사용할 수 있지만 여기서는 CallBack이 없습니다. 그래서 우리는 첫 번째 클라이언트 프로세스에서 델리게이트가 호출되는지 확인하기 위해 첫 번째 클라이언트에서 RemoteObject로 콜백 채널을 등록해야합니다. 디버깅 목적으로 프로세스 ID를 추가했습니다.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
const string PIPE_NAME = "testPipeName33";
const string OBJECT_NAME = "test";
const string CALLBACK_PIPE_NAME = "testPipeName34";
const string CALLBACK_OBJECT_NAME = "testclient";
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if ((args.Length == 0 || args[0] == "s"))
{
try
{
IPCRegistration.RegisterServer(PIPE_NAME,OBJECT_NAME);
}
catch (RemotingException)
{
remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject),PIPE_NAME,OBJECT_NAME);
remoteObject.OnNewProcessStarted("test");
Application.Exit();
return;
}
MessageBox.Show("Server:" + Process.GetCurrentProcess().Id);
Process.Start(Application.ExecutablePath, "c");
Application.Run(new Form1("Server"));
}
else
{
IsClient = true;
remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject), PIPE_NAME, OBJECT_NAME);
IPCRegistration.RegisterServer(CALLBACK_PIPE_NAME, CALLBACK_OBJECT_NAME); // Here Client will listen on this channel.
remoteObject.SetOnNewProcessStarted(OnNewProcessStarted,Process.GetCurrentProcess().Id.ToString());
MessageBox.Show("Client:" + Process.GetCurrentProcess().Id);
Application.Run(new Form1("Client"));
}
}
static RemoteObject remoteObject;
static bool IsClient = false;
static bool OnNewProcessStarted(string commandLine)
{
MessageBox.Show("saved:"+commandLine+" Currrent:"+Process.GetCurrentProcess().Id);
MessageBox.Show("Is Client : " + IsClient);//problem here, IsClient should be true
return true;
}
}
public delegate bool OnNewProcessStartedDelegate(string text);
internal class RemoteObject : MarshalByRefObject
{
public OnNewProcessStartedDelegate OnNewProcessStartedHandler;
public string value;
public bool isCallBack = false;
const string PIPE_NAME = "testPipeName33";
const string OBJECT_NAME = "test";
const string CALLBACK_PIPE_NAME = "testPipeName34";
const string CALLBACK_OBJECT_NAME = "testclient";
RemoteObject remoteObject;
public bool OnNewProcessStarted(string commandLine)
{
if (!isCallBack)
{
remoteObject.isCallBack = true;
return remoteObject.OnNewProcessStarted(commandLine);
}
if (OnNewProcessStartedHandler != null)
return OnNewProcessStartedHandler(value);
return false;
}
public void SetOnNewProcessStarted(OnNewProcessStartedDelegate onNewProcessStarted,string value)
{
this.value = value;
OnNewProcessStartedHandler = onNewProcessStarted;
if (!isCallBack)
{
remoteObject = IPCRegistration.RegisterClient(typeof(RemoteObject), CALLBACK_PIPE_NAME, CALLBACK_OBJECT_NAME);
remoteObject.isCallBack = true;
remoteObject.SetOnNewProcessStarted(onNewProcessStarted, Process.GetCurrentProcess().Id.ToString());
}
}
public override object InitializeLifetimeService()
{
return null;
}
}
internal class IPCRegistration
{
public static RemoteObject RegisterClient(Type remoteObject,string PIPE_NAME,string OBJECT_NAME)
{
IpcClientChannel chan = new IpcClientChannel();
ChannelServices.RegisterChannel(chan, false);
RemoteObject remoteObjectInstance = (RemoteObject)Activator.GetObject(remoteObject,
string.Format("ipc://{0}/{1}", PIPE_NAME, OBJECT_NAME));
return remoteObjectInstance;
}
public static void RegisterServer(string pipeName, string objectName)
{
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
IpcServerChannel chan = new IpcServerChannel("", pipeName, serverProvider);
ChannelServices.RegisterChannel(chan, false);
RemotingServices.Marshal(new RemoteObject(), objectName);
}
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다