[.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 02.10.10 14:02
Оценка:
Вчерновую накидал cross-process singleton на named pipes, плиз потыкайте носом

Ясен пень, что до юзабельного состояния пилить и пилить: вынести в отдельный класс, добавить разные имена для разных сессий, не забыть про обработку ошибок, запуск в фоновом потоке, прерывание работы и т.д. и т.п.

Меня сейчас интересуют в первую очередь упущенные нюансы/неверно указанные параметры/безопасность. Например, я почти уверен, что в коде дырка: не блокируются удалённые соединения. В понедельник буду на работе, проверю.

  код
using System;
using System.IO;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;

namespace ProcessSingleInstance
{
  class Program
  {
    static void Main(string[] args)
    {
      string[] data = new[] { "a", "aaaaa", "qweqeqweqeqweqwert" };

      NamedPipeServerStream server = null;
      try
      {
        server = CreateServerStream();
      }
      catch (UnauthorizedAccessException)
      {
      }

      if (server != null)
      {
        RunServer(server);
      }
      else
      {
        RunClient(data);
      }
    }

    // критиковать здесь.
    // Сервер должен _только_ читать данные;
    // не должен позволять соединения вне текущей сессии, в т.ч. удалённые
    private static NamedPipeServerStream CreateServerStream()
    {
      PipeSecurity security = new PipeSecurity();

      security.AddAccessRule(
        new PipeAccessRule(
          WindowsIdentity.GetCurrent().User,
          PipeAccessRights.Synchronize
          | PipeAccessRights.ReadAttributes // DONTTOUCH: Required. I don't know why.
          | PipeAccessRights.Write,
          AccessControlType.Allow));

      NamedPipeServerStream server = new NamedPipeServerStream(
        "server",
         PipeDirection.In, 1,
         PipeTransmissionMode.Message, PipeOptions.WriteThrough, // Не уверен. Может, всё-таки использовать буфер?
         4096, 4096,
         security, HandleInheritability.None);

      return server;
    }

    // и здесь
    private static NamedPipeClientStream CreateClientStream()
    {
      NamedPipeClientStream client = new NamedPipeClientStream(
        ".", "server",
        PipeDirection.Out, PipeOptions.WriteThrough, TokenImpersonationLevel.None, HandleInheritability.None);
      
      return client;
    }

    private static void RunServer(NamedPipeServerStream server)
    {
      while (true)
      {
        Console.WriteLine("Wait...");
        BinaryReader r = new BinaryReader(server);
        server.WaitForConnection();

        try
        {
          int count = r.ReadInt32();
          for (int i = 0; i < count; i++)
          {
            Console.WriteLine(r.ReadString());
          }
        }
        catch (IOException)
        { }

        server.Disconnect();
      }
    }
    private static void RunClient(string[] data)
    {
      using (NamedPipeClientStream client = CreateClientStream())
      {
        client.Connect();
        using (BinaryWriter w = new BinaryWriter(client))
        {
          try
          {
            w.Write(data.Length);
            foreach (var item in data)
            {
              w.Write(item);
            }

            client.WaitForPipeDrain();
          }
          catch (IOException)
          { }
        }
      }
    }
  }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.