ネットワーク上に 2 つのクライアント (Client-PC1 + Client-PC2) があります。そのクライアントのそれぞれで、小さな c# フォーム/コンソール アプリケーションを実行するのが好きで、そのアプリケーション間で通信するのが好きです。
Client-PC1 から Client-PC2 でアプリケーションをトリガーしたいと考えています。(コード部分: menuItem1_Click) 私はすでにいくつかの調査を行っており、TechNet で次の記事を見つけました:方法: ネットワーク プロセス間通信に名前付きパイプを使用する
しかし、間違いまたは誤解が 1 つあります。サーバー側では、処理できる特定の数のスレッドがあります (現時点では、numThreads = 4)。
したがって、Client-PC1 から 4 回以上トリガーすると、サーバー側 (Client-PC2) がアプリケーション全体を閉じています...
このコードを変更して、4 つ以上のリクエスト/トリガーを受け入れるにはどうすればよいですか? 合計で、サーバーに接続するが複数の要求を送信するコンピューターは 1 ~ 2 台しかありません。
リクエスト/トリガーを送信した後、クライアント側で何か問題があると思いますか?
何か案は?
クライアントコード:
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace NamedPipe_Client
{
class Program
{
private static int numClients = 4;
private static bool isConnected = false;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.ContextMenu contextMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.ComponentModel.IContainer components;
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void Main(string[] args)
{
Program pg = new Program();
//pg.CreateNotifyicon();
Application.Run();
Console.ReadLine();
}
Program()
{
CreateNotifyicon();
// hide application
System.IntPtr HWnd = FindWindow(null, Application.ExecutablePath);
if (HWnd != null)
{
bool result = ShowWindow(HWnd, 0);
}
}
private void CreateNotifyicon()
{
this.components = new System.ComponentModel.Container();
this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
// Initialize menuItem1
this.menuItem1.Index = 0;
this.menuItem1.Text = "E&xit";
this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);
// Initialize contextMenu1
this.contextMenu1.MenuItems.AddRange(
new System.Windows.Forms.MenuItem[] { this.menuItem1 });
// Create the NotifyIcon.
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
// The Icon property sets the icon that will appear
// in the systray for this application.
notifyIcon1.Icon = new Icon("app_icon.ico");
// The ContextMenu property sets the menu that will
// appear when the systray icon is right clicked.
notifyIcon1.ContextMenu = this.contextMenu1;
// The Text property sets the text that will be displayed,
// in a tooltip, when the mouse hovers over the systray icon.
notifyIcon1.Text = "Console App (Console example)";
notifyIcon1.Visible = true;
// Handle the DoubleClick event to activate the form.
notifyIcon1.DoubleClick += new System.EventHandler(this.notifyIcon1_DoubleClick);
notifyIcon1.Click += new System.EventHandler(this.notifyIcon1_Click);
}
private void notifyIcon1_Click(object Sender, EventArgs e)
{
MessageBox.Show("clicked");
}
private void notifyIcon1_DoubleClick(object Sender, EventArgs e)
{
MessageBox.Show("Double clicked");
}
private void menuItem1_Click(object Sender, EventArgs e)//on menu click exit.
{
//Show application again
//System.IntPtr HWnd = FindWindow(null, Application.ExecutablePath);
//if (HWnd != null)
//{
// bool result = ShowWindow(HWnd, 1);
//}
NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "testpipe",
PipeDirection.InOut, PipeOptions.None,
TokenImpersonationLevel.Impersonation);
Console.WriteLine("Connecting to server...\n");
pipeClient.Connect();
StreamString ss = new StreamString(pipeClient);
// Validate the server's signature string
if (ss.ReadString() == "I am the one true server!")
{
// The client security token is sent with the first write.
// Send the name of the file whose contents are returned
// by the server.
//ss.WriteString(@"C:\Test\textfile.txt");
ss.WriteString("Test");
// Print the file to the screen.
Console.Write(ss.ReadString());
}
else
{
Console.WriteLine("Server could not be verified.");
}
pipeClient.Close();
}
// Helper function to create pipe client processes
private static void StartClients()
{
int i;
string currentProcessName = Environment.CommandLine;
Process[] plist = new Process[numClients];
Console.WriteLine("Spawning client processes...\n");
if (currentProcessName.Contains(Environment.CurrentDirectory))
{
currentProcessName = currentProcessName.Replace(Environment.CurrentDirectory, String.Empty);
}
// Remove extra characters when launched from Visual Studio
currentProcessName = currentProcessName.Replace("\\", String.Empty);
currentProcessName = currentProcessName.Replace("\"", String.Empty);
for (i = 0; i < numClients; i++)
{
// Start 'this' program but spawn a named pipe client.
plist[i] = Process.Start(currentProcessName, "spawnclient");
}
while (i > 0)
{
for (int j = 0; j < numClients; j++)
{
if (plist[j] != null)
{
if (plist[j].HasExited)
{
Console.WriteLine("Client process[{0}] has exited.",
plist[j].Id);
plist[j] = null;
i--; // decrement the process watch count
}
else
{
Thread.Sleep(250);
}
}
}
}
Console.WriteLine("\nClient processes finished, exiting.");
}
}
// Defines the data protocol for reading and writing strings on our stream
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len;
len = ioStream.ReadByte() * 256;
len += ioStream.ReadByte();
byte[] inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
ioStream.WriteByte((byte)(len / 256));
ioStream.WriteByte((byte)(len & 255));
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + 2;
}
}
}
サーバーコード:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace NamedPipe_Server
{
class Program
{
private static int numThreads = 4;
static void Main(string[] args)
{
int i;
Thread[] servers = new Thread[numThreads];
Console.WriteLine("\n*** Named pipe server stream with impersonation example ***\n");
Console.WriteLine("Waiting for client connect...\n");
for (i = 0; i < numThreads; i++)
{
servers[i] = new Thread(ServerThread);
servers[i].Start();
}
Thread.Sleep(250);
while (i > 0)
{
for (int j = 0; j < numThreads; j++)
{
if (servers[j] != null)
{
if (servers[j].Join(250))
{
Console.WriteLine("Server thread[{0}] finished.", servers[j].ManagedThreadId);
servers[j] = null;
i--; // decrement the thread watch count
}
}
}
}
Console.WriteLine("\nServer threads exhausted, exiting.");
}
private static void ServerThread(object data)
{
NamedPipeServerStream pipeServer =
new NamedPipeServerStream("testpipe", PipeDirection.InOut, numThreads);
int threadId = Thread.CurrentThread.ManagedThreadId;
// Wait for a client to connect
pipeServer.WaitForConnection();
Console.WriteLine("Client connected on thread[{0}].", threadId);
try
{
// Read the request from the client. Once the client has
// written to the pipe its security token will be available.
StreamString ss = new StreamString(pipeServer);
// Verify our identity to the connected client using a
// string that the client anticipates.
ss.WriteString("I am the one true server!");
string filename = ss.ReadString();
if (filename.ToString() == "Test")
{
Console.WriteLine("yes");
ss.WriteString("Done");
}
// Read in the contents of the file while impersonating the client.
//ReadFileToStream fileReader = new ReadFileToStream(ss, filename);
// Display the name of the user we are impersonating.
//Console.WriteLine("Reading file: {0} on thread[{1}] as user: {2}.",
// filename, threadId, pipeServer.GetImpersonationUserName());
//pipeServer.RunAsClient(fileReader.Start);
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
pipeServer.Close();
}
}
// Defines the data protocol for reading and writing strings on our stream
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len = 0;
len = ioStream.ReadByte() * 256;
len += ioStream.ReadByte();
byte[] inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
ioStream.WriteByte((byte)(len / 256));
ioStream.WriteByte((byte)(len & 255));
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + 2;
}
}
// Contains the method executed in the context of the impersonated user
public class ReadFileToStream
{
private string fn;
private StreamString ss;
public ReadFileToStream(StreamString str, string filename)
{
fn = filename;
ss = str;
}
public void Start()
{
string contents = File.ReadAllText(fn);
ss.WriteString(contents);
}
}
}