gpt4 book ai didi

c# - 命名管道可以执行我想做的事吗?

转载 作者:太空宇宙 更新时间:2023-11-03 23:28:16 24 4
gpt4 key购买 nike

这是II期,我在前一周发布,而my question被搁置,我调整了我的文字,但没有得到评论,系统关闭了原始帖子。

逻辑

服务器端:只读-服务器打开管道,然后定期检查是否有内容(即不在流末尾)并读取信息。此检查必须基于轮询,因为仅在轮询期间存在有效的上下文才能传递数据。

客户端:仅写-打开管道,写入管道,关闭(client.exe被调用多次,寿命短,下面的代码是测试代码),例如其他一些脚本将“使用信息调用client.exe”


可以在管道中处理此工作流程吗?例如客户端代码的片段仅显示“服务器”看到的第一条客户端消息
如果管道可以在编码提示后执行此操作,因为大多数示例适用于客户端-具有相似生命周期的服务器。


代码段

    for (int i = 0; i < 10; i++)
{
//Client - simulate exe starting and ending
var client = new NamedPipeClientStream(".", "PipesOfPiece", PipeDirection.Out, PipeOptions.WriteThrough);
client.Connect();
StreamWriter writer = new StreamWriter(client);

Console.WriteLine("Client about to send message");
writer.WriteLine("Called from client i = {0}", i);

writer.Close();
client.Close();

Thread.Sleep(5000);
}
// server snippet
var server = new NamedPipeServerStream("PipesOfPiece", PipeDirection.In);
server.WaitForConnection(); <= can this we optional with code below
StreamReader reader = new StreamReader(server);
while (true)
{
// simulate start of poll code
if (server.IsConnected)
{
if (!reader.EndOfStream)
{
var line = reader.ReadToEnd();
Console.WriteLine("Server: {0}", line);
}
} // End of poll code
Thread.Sleep(1000);
}
// server snippet
var server = new NamedPipeServerStream("PipesOfPiece", PipeDirection.In);
server.WaitForConnection(); <= can this we optional with code below
StreamReader reader = new StreamReader(server);
while (true)
{
// simulate start of poll code
if (server.IsConnected)
{
if (!reader.EndOfStream)
{
var line = reader.ReadToEnd();
Console.WriteLine("Server: {0}", line);
}
} // End of poll code
Thread.Sleep(1000);
}


因此,我对管道不满意,希望管道可以打开,写入然后读取,并且在需要的情况下可以使用waitforconnect(),它是可选的。我想这一切都是在谁拥有管道的情况下触发的,即,如果服务器打开了管道并正在等待有人为其编写管道,为什么它需要等待连接? (我希望服务器是所有者,以便在服务器结束时管道消失)

最佳答案

没有a good, minimal, complete code example可以可靠地重现您遇到的任何具体问题,就无法提供有关如何解决该问题的具体建议。但是,我至少可以尝试回答您有关如何使用命名管道的一些问题,并提供一个代码示例来说明一些概念。


首先,一些规则和观察:


管道实例只能用于一个连接。请注意,管道继承了Stream,流具有非常特定的范例:打开一个范例,读到最后,然后就完成了流。有些流(例如FileStream)是可搜索的,但即使在那里,您也只能处理单个资源(即原始文件……您无法将FileStream重新连接到另一个文件),而网络流甚至都没有寻找。
在对其执行I / O之前,必须先连接管道。
您可能有多个具有相同名称的管道实例(如果正确初始化它们……默认情况下,您可能只有一个名称相同的管道)。
尝试连接到命名管道的客户端将等待,直到该管道存在。客户端启动连接时,它不需要存在。
只有一个客户端可以连接到管道的任何给定实例。服务器管道的任何给定实例只能在其整个生命周期内处理单个客户端(请参见上面的第一点)。


那么,您的问题呢?




  可以在管道中处理此工作流程吗?


如果我正确理解工作流程,可以。但是您需要注意正确实施它。

据我了解,您希望服务器仅尝试定期从客户端读取数据。同时,您希望客户端能够随时写入管道。可以做到这一点,但并非一帆风顺。

请注意,根据以上内容,您无法打开单个服务器管道,然后让多个客户端定期连接和断开该管道。一旦第一个客户端已连接,该管道将不再可用。这是一个流,并且第一个客户端的断开连接导致该流到达其末端。完成。

还请注意,虽然客户端可以尝试连接到尚不存在的管道,但它将等待直到可以。因此,如果您希望客户不必等到轮询间隔期满,就需要保持可随时连接的服务器管道。

但是您已经说过,您将无法在任意时间点处理从服务器管道读取的数据,而只能在轮询间隔内处理。

由于管道本身并不支持这种特定情况,因此恕我直言,实现它的正确方法是将行为分为两个不同的组件。维护一个简单的管道服务器,该服务器将打开管道,等待客户端连接,读取客户端发送的内容,关闭管道,然后重新开始。

然后有一个中间类,可以充当服务器I / O和最终拥有数据的任何组件之间的中介。该中介将在收到数据后保留一份副本(无论轮询间隔如何,管道代码都会在收到数据后立即将其传送给中介);然后,轮询组件随后将在下一个轮询间隔(即,当您所说的“上下文”实际上可用于向其传递数据)时检索数据。


  我希望可以打开,写入然后读取的管道,并且在需要的情况下可以使用waitforconnect(),它是可选的


不幸的是,您的希望与现实不符。管道可以是双向的;即“先写再读”。但是WaitForConnect()不是可选的。服务器必须先等待连接,然后才能尝试从管道读取数据,对于该管道实例,服务器将只能从单个客户端接收数据。


  我希望服务器是所有者,以便在服务器结束时管道消失


服务器进程是实际创建管道的进程。所以是的,从这个意义上说,它是所有者。是的,当服务器进程终止时,它创建的所有管道都会被销毁。


在下面,请找到一个简单的代码示例,该示例说明了多个并发服务器和客户端的用法。您可以使用示例顶部的声明常量来调整每个数字。

在运行它时,请注意,如果活动的客户端数量多于服务器数量,则其他客户端将仅等待直到可以连接服务器管道为止。一旦建立,它们将连接并正常进行。如果至少有与尝试连接的客户端数量相等的服务器管道实例,则将同时为所有客户端提供服务。

// NOTE: as a sample program, contrary to normal and correct
// programming practices error-handling has been omitted, and
// non-awaited async methods have been declared as void.
class Program
{
private const string _kserverName = "TestSO33093954NamedPipeClients";
private const int _kmaxServerCount = 3;
private const int _kmaxClientCount = 3;

static void Main(string[] args)
{
StartServers(_kmaxServerCount);
StartClients(_kmaxClientCount);

Console.WriteLine("Clients are being started. Press return to exit program.");
Console.ReadLine();
}

private static async void StartClients(int clientCount)
{
for (int i = 0; i < clientCount; i++)
{
RunClient(i);
await Task.Delay(300);
}
}

private static async void RunClient(int instance)
{
NamedPipeClientStream client = new NamedPipeClientStream(
".", _kserverName, PipeDirection.InOut, PipeOptions.Asynchronous);

client.Connect();

ReadClient(client);

using (StreamWriter writer = new StreamWriter(client))
{
writer.AutoFlush = true;

for (int i = 0; i < 5; i++)
{
string text =
string.Format("Instance #{0}, iteration #{1}", instance, i);

Console.WriteLine("Client send: " + text);
await writer.WriteLineAsync(text);
await Task.Delay(1000);
}

client.WaitForPipeDrain();
}
}

private static async void ReadClient(Stream stream)
{
using (TextReader reader = new StreamReader(stream))
{
string line;

while ((line = await reader.ReadLineAsync()) != null)
{
Console.WriteLine("Client recv: " + line);
}
}
}

private static void StartServers(int maxServerInstances)
{
for (int i = 0; i < maxServerInstances; i++)
{
RunServer(maxServerInstances);
}
}

private static async void RunServer(int maxServerInstances)
{
while (true)
{
using (NamedPipeServerStream server = new NamedPipeServerStream(
_kserverName, PipeDirection.InOut, maxServerInstances,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
await server.WaitForConnectionAsync();

byte[] buffer = new byte[1024];
int bytesRead;
Decoder decoder = Encoding.UTF8.GetDecoder();

while ((bytesRead =
await server.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
int cch = decoder.GetCharCount(buffer, 0, bytesRead);
char[] rgch = new char[cch];

decoder.GetChars(buffer, 0, bytesRead, rgch, 0);
Console.Write("Server recv: " + new string(rgch));

await server.WriteAsync(buffer, 0, bytesRead);
}
}
}
}
}

static class PipeExtensions
{
// As I am not running with .NET 4.6 yet, I need this little helper extension
// to wrap the APM-based asynchronous connection-waiting with the await-friendly
// Task-based syntax. Anyone using .NET 4.6 will have this in the framework already
public static Task WaitForConnectionAsync(this NamedPipeServerStream server)
{
return Task.Factory.FromAsync(
server.BeginWaitForConnection, server.EndWaitForConnection, null);
}
}

关于c# - 命名管道可以执行我想做的事吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33093954/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com