Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обмен данными, между процессами 
V
    Опции темы
Alexsar
  Дата 26.5.2006, 23:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: 2
Всего: 1



Всем привет smile 
Задача: есть два процесса, они выполняют свою работу и обмениваются данными между собой
Как это сделать проще всего?
Например, пусть первый процесс передаёт второму массив А, а второй первому В
Нужен пример кода на С#
 smile  
PM MAIL   Вверх
mr.DUDA
Дата 27.5.2006, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Статья о Remoting на русском, там есть простые примеры:

http://rsdn.ru/article/dotnet/inside_remoting1.xml 


--------------------
user posted image
PM MAIL WWW   Вверх
Alexsar
Дата 3.6.2006, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: 2
Всего: 1



как обращаться клиенту к удалённому объекту понятно, а как сервер может обращаться к объекту не ясно

вот код объекта:

Код

using System;
using System.Runtime.Remoting;

// Remote object.
public class RemoteObject : MarshalByRefObject
{
    private int callCount = 0;

    public int GetCount()
    {
        callCount++;
        return(callCount);
    }
    
    public double CALL{
    get{return callCount;}
    set{callCount=value;}
    }
}



вот код сервера:

Код

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Security.Permissions;

public class Server
{
[SecurityPermission(SecurityAction.Demand)]
    public static void Main(string[] args)
    {
        // Create the server channel.
        TcpChannel serverChannel = new TcpChannel(9090);

        // Register the server channel.
        ChannelServices.RegisterChannel(serverChannel);

        // Show the name of the channel.
        Console.WriteLine("The name of the channel is {0}.", 
            serverChannel.ChannelName);

        // Show the priority of the channel.
        Console.WriteLine("The priority of the channel is {0}.", 
            serverChannel.ChannelPriority);

        // Show the URIs associated with the channel.
        ChannelDataStore data = (ChannelDataStore) serverChannel.ChannelData;
        foreach (string uri in data.ChannelUris)
        {
            Console.WriteLine("The channel URI is {0}.", uri);
        }

        // Expose an object for remote calls.
        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(RemoteObject), "RemoteObject.rem", 
            WellKnownObjectMode.Singleton);

        // Parse the channel's URI.
        string[] urls = serverChannel.GetUrlsForUri("RemoteObject.rem");
        if (urls.Length > 0)
        {
            string objectUrl = urls[0];
            string objectUri;
            string channelUri = serverChannel.Parse(objectUrl, out objectUri);
            Console.WriteLine("The object URL is {0}.", objectUrl);
            Console.WriteLine("The object URI is {0}.", objectUri);
            Console.WriteLine("The channel URI is {0}.", channelUri);
        }
        
        // Wait for the user prompt.
        RemoteObject service = new RemoteObject();

      Console.ReadLine();
      service.CALL=30;
        

        Console.WriteLine("Press ENTER to exit the server.");
        Console.ReadLine();
    }
}




по идее он должен установить для удалённого объекта 30 в поле: CallCount, но этого не делает

хотя если использовать 2 и более клиентов они могут справиться с данной задачей

вот код клиента №1:

Код

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Security.Permissions;

public class Client
{
[SecurityPermission(SecurityAction.Demand)]
    public static void Main(string[] args)
    {
        // Create the channel.
        TcpChannel clientChannel = new TcpChannel();

        // Register the channel.
        ChannelServices.RegisterChannel(clientChannel);

        // Register as client for remote object.
        WellKnownClientTypeEntry remoteType = new WellKnownClientTypeEntry(
            typeof(RemoteObject),"tcp://localhost:9090/RemoteObject.rem");
        RemotingConfiguration.RegisterWellKnownClientType(remoteType);

        // Create a message sink.
        string objectUri;
        System.Runtime.Remoting.Messaging.IMessageSink messageSink = 
            clientChannel.CreateMessageSink(
                "tcp://localhost:9090/RemoteObject.rem", null,
                out objectUri);
        Console.WriteLine("The URI of the message sink is {0}.", 
            objectUri);
        if (messageSink != null)
        {
            Console.WriteLine("The type of the message sink is {0}.", 
                messageSink.GetType().ToString());
        }

        // Create an instance of the remote object.
        RemoteObject service = new RemoteObject(); 

        // Invoke a method on the remote object.
        Console.WriteLine("The client is invoking the remote object.");
        Console.WriteLine("The remote object has been called {0} times.",
            service.GetCount());
        Console.WriteLine("Запусти clietn2.exe");
      Console.ReadLine();
        Console.WriteLine("Стало: {0}",service.CALL);
      Console.ReadLine();
    }
}




код клиента №2:

Код

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Security.Permissions;

public class Client
{
[SecurityPermission(SecurityAction.Demand)]
    public static void Main(string[] args)
    {
        // Create the channel.
        TcpChannel clientChannel = new TcpChannel();

        // Register the channel.
        ChannelServices.RegisterChannel(clientChannel);

        // Register as client for remote object.
        WellKnownClientTypeEntry remoteType = new WellKnownClientTypeEntry(
            typeof(RemoteObject),"tcp://localhost:9090/RemoteObject.rem");
        RemotingConfiguration.RegisterWellKnownClientType(remoteType);

        // Create a message sink.
        string objectUri;
        System.Runtime.Remoting.Messaging.IMessageSink messageSink = 
            clientChannel.CreateMessageSink(
                "tcp://localhost:9090/RemoteObject.rem", null,
                out objectUri);
        Console.WriteLine("The URI of the message sink is {0}.", 
            objectUri);
        if (messageSink != null)
        {
            Console.WriteLine("The type of the message sink is {0}.", 
                messageSink.GetType().ToString());
        }

        // Create an instance of the remote object.
        RemoteObject service = new RemoteObject(); 

        // Invoke a method on the remote object.
        Console.WriteLine("Input number");
        int call = int.Parse(Console.ReadLine());
        service.CALL=call;
        Console.WriteLine("стало {0}",service.CALL);
        Console.WriteLine("теперь нажми ENTER в приложении client.exe");
      Console.ReadLine();
    }
}




итог такой: при запуске сервера, поле CallCount всё равно =0, если же запустить первый клиент он инкременирует это поле посредством функции GetCount()
затем при запуске второго клиента, пользователь может установить это поле в любое состояние, и этот результат очевиден если нажать клавишу энтер в первом клиентском приложении

в принципе таким образом можно осуществить передачу данных между 2-я приложениями, но для этого приходится запускать 3 процесса, что выглядит коряво smile 

очень хочется понять, как сервер может изменять состояние объекта или хотя бы пример кода, который использует винайпишные функции smile  
PM MAIL   Вверх
Alexsar
Дата 10.6.2006, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: 2
Всего: 1



в продолжении темы
решил попробовать использовать айпишные функции
хочу передавать данные посредством отображения в память
теперь 2 процесса: сервер и клиент
но проблема-не знаю как записать и считать данные по полученному адресу
в обычном Си легко это делаю с помощью команд putch(*((LPSTR)lpFileMap)) и *((LPSTR)lpFileMap) = chr
где chr-типа char
но в С# нет типа анлогичных HANDLE, LPVOID, там есть только один IntPtr
в пиведённом ниже коде получаю указатель на отображаемую область памяти, но как изменить содержимое, и как считать данные не знаю smile 
работа прог заключается в следущем: когда в клиенте что-нибудь вводишь, то этот символ должен отображаться в сервере.

как правильно это сделать?
вот код сервера:

Код

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text;
using System.Security.Permissions;

namespace MapS
{
    class Program
    {
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateEvent(IntPtr even, bool tf1, bool tf2, string name);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFileMapping(UIntPtr even, IntPtr even2, Int32 falgs, Int32 a, Int32 b, string name);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr MapViewOfFile(IntPtr hMap, Int32 flags, Int32 a, Int32 b, Int32 c);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern UInt32 WaitForMultipleObjects(Int32 n, IntPtr[] handl, bool flags, UInt32 atr);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern void CloseHandle(IntPtr hEvent);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern void UnmapViewOfFile(IntPtr lpFileMap);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern Int32 GetLastError();

        const int ERROR_ALREADY_EXISTS = 0xb7;
        const int PAGE_READWRITE = 0x4;
        const int FILE_MAP_READ = 0x4;
        const int FILE_MAP_WRITE = 0x2;
        const uint INFINITE = 0xffffffff;
        const int WAIT_ABANDONED_0 = 0x80;
        const int WAIT_OBJECT_0 = 0x0;
        const uint WAIT_FAILED = 0xffffffff;


        static void Main(string[] args)
        {
            // Идентификаторы объектов-событий, которые используются
            // для синхронизации задач, принадлежащих разным процессам
            IntPtr hEventChar;
            IntPtr hEventTermination;
            IntPtr[] hEvents = new IntPtr[2];

            // Имя объекта-события для синхронизации ввода и отображения
            string lpEventName = "MyVerySpecialEventName";

            // Имя объекта-события для завершения процесса
            string lpEventTerminationName = "MyVerySpecialEventTerminationName";

            // Имя отображния файла на память
            string lpFileShareName = "MyVerySpecialFileShareName";

            // Идентификатор отображения файла на память
            IntPtr hFileMapping;

            // Указатель на отображенную область памяти
            IntPtr lpFileMap;
            
            UInt32 dwRetCode;
            // Создаем объект-событие для синхронизации 
            // ввода и отображения, выполняемого в разных процессах
            hEventChar = CreateEvent(IntPtr.Zero, false, false, lpEventName);  
            
            // Если произошла ошибка, получаем и отображаем ее код,
            // а затем завершаем работу приложения
            if(hEventChar == IntPtr.Zero)
            {
                Console.WriteLine("CreateEvent: Error {0}\n",GetLastError());
                Console.ReadKey();
                return;
            }
            
            // Если объект-событие с указанным именем существует,
            // считаем, что приложение EVENT уже было запущено
            if(GetLastError() == ERROR_ALREADY_EXISTS)
            {
                Console.WriteLine("Application EVENT already started\nPress any key to exit...");
                Console.ReadKey();
                return;
            }
            
            // Создаем объект-событие для определения момента
            // завершения работы процесса ввода
            hEventTermination = CreateEvent(IntPtr.Zero, false, false, lpEventTerminationName);
            
            if(hEventTermination == IntPtr.Zero)
            {
                Console.WriteLine("CreateEvent (Termination): Error {0}",GetLastError());
                Console.ReadKey();
                return ;
            }
            
            // Создаем объект-отображение
            hFileMapping = CreateFileMapping((UIntPtr)0xFFFFFFFF, IntPtr.Zero, PAGE_READWRITE, 0, 100, lpFileShareName);
            
            // Если создать не удалось, выводим код ошибки
            if(hFileMapping == IntPtr.Zero)
            {
                Console.WriteLine("CreateFileMapping: Error {0}",GetLastError());
                Console.ReadKey();
                return;
            }
            // Выполняем отображение файла на память
            // В переменную lpFileMap будет записан указатель на
            // отображаемую область памяти
            lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
            
            // Если выполнить отображение не удалось,
            // выводим код ошибки
            if(lpFileMap.ToInt32() == 0)
            {
                Console.WriteLine("MapViewOfFile: Error {0}",GetLastError());
                Console.ReadKey();
                return;
            }
            
            // Готовим массив идентификаторов событий
            // для функции WaitForMultipleObjects
            hEvents[0] = hEventTermination;
            hEvents[1] = hEventChar;

            // Цикл отображения. Этот цикл завершает свою работу
            // при завершении процесса ввода
            Console.WriteLine("Ждёмс\n");

            while(true)
            {
                // Выполняем ожидание одного из двух событий:
                //   - завершение клиентского процесса;
                //   - завершение ввода символа
                dwRetCode = WaitForMultipleObjects(2,hEvents, false, INFINITE);

                // Если ожидание любого из двух событий было отменено,
                // если произошло первое событие (завершение клиентского
                // процесса) или если произошла ошибка, прерываем цикл
                if(dwRetCode == WAIT_ABANDONED_0 ||dwRetCode == WAIT_ABANDONED_0 + 1 ||
                    dwRetCode == WAIT_OBJECT_0 || dwRetCode == WAIT_FAILED)
                    break;


                // Читаем символ из первого байта отображенной
                // области памяти, записанный туда клиентским 
                // процессом, и отображаем его в консольном окне
                //КАК ПРАВИЛЬНО ЭТО СДЕЛАТЬ?
                Console.Write(lpFileMap+"\n");

            }
            
            // Закрываем идентификаторы объектов-событий  
            CloseHandle(hEventChar);
            CloseHandle(hEventTermination);

            // Отменяем отображение файла
            UnmapViewOfFile(lpFileMap);

            // Освобождаем идентификатор созданного
            // объекта-отображения
            CloseHandle(hFileMapping);
            Console.ReadLine();
        }
    }
}



вот код клиента

Код

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Text;
using System.Security.Permissions;
using System.Windows.Forms;


[assembly: UIPermissionAttribute(SecurityAction.RequestMinimum, Clipboard = UIPermissionClipboard.AllClipboard, Window = UIPermissionWindow.AllWindows)]

namespace MapC
{
    class Program
    {
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenEvent(Int32 flags, bool tf, string name);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenFileMapping(Int32 flags, bool tf, string name);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, Int32 flags, Int32 a, Int32 b, Int32 c);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern void SetEvent(IntPtr hEvent);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern void CloseHandle(IntPtr hEvent);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern void UnmapViewOfFile(IntPtr lpFileMap);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern Int32 GetLastError();

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool WriteFile(IntPtr handle, IntPtr buf, Int64 siz, IntPtr kol, IntPtr atr);


        
        const int EVENT_ALL_ACCESS = 0x1f0003;
        const int FILE_MAP_READ = 0x4;
        const int FILE_MAP_WRITE = 0x2;

        static void Main(string[] args)
        {

            // Идентификаторы объектов-событий, которые используются
            // для синхронизации задач, принадлежащих разным процессам
            IntPtr hEvent;
            IntPtr hEventTermination;

            // Имя объекта-события для синхронизации ввода и отображения
            string lpEventName = "MyVerySpecialEventName";

            // Имя объекта-события для завершения процесса
            string lpEventTerminationName = "MyVerySpecialEventTerminationName";

            // Имя отображния файла на память
            string lpFileShareName = "MyVerySpecialFileShareName";

            // Идентификатор отображения файла на память
            IntPtr hFileMapping;

            // Указатель на отображенную область памяти
            IntPtr lpFileMap;

            char chr;

                   
            // Открываем объект-событие для синхронизации 
            // ввода и отображения
            hEvent = OpenEvent(EVENT_ALL_ACCESS, false, lpEventName);

            if (hEvent == IntPtr.Zero)
            {
                Console.WriteLine("OpenEvent: Error {0}", GetLastError());
                Console.ReadKey();
                return;
            }

            // Открываем объект-событие для сигнализации о
            // завершении процесса ввода
            hEventTermination = OpenEvent(EVENT_ALL_ACCESS, false, lpEventTerminationName);
  
            if(hEventTermination == IntPtr.Zero)
            {
                Console.WriteLine("OpenEvent (Termination): Error {0}", GetLastError());
                Console.ReadKey();
                return;
            }

            // Открываем объект-отображение
            hFileMapping = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, false, lpFileShareName);

            // Если открыть не удалось, выводим код ошибки
            if(hFileMapping == IntPtr.Zero)
            {
                Console.WriteLine("OpenFileMapping: Error {0}",GetLastError());
                Console.ReadKey();
                return;
            }

            // Выполняем отображение файла на память.
            // В переменную lpFileMap будет записан указатель на
            // отображаемую область памяти
            lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);


            // Если выполнить отображение не удалось,
            // выводим код ошибки
            if(lpFileMap.ToInt32() == 0)
            {
                Console.WriteLine("MapViewOfFile: Error {0}",GetLastError());
                Console.ReadKey();
                return;
            }


            Console.WriteLine("Введите что нибудь\n");

            // Цикл ввода. Этот цикл завершает свою работу,
            // когда пользователь нажимает клавишу <ESC>, 
            // имеющую код 27

            while (true)
            {
                // Проверяем код введенной клавиши
                chr = Console.ReadKey().KeyChar;

                // Если нажали клавишу <ESC>, прерываем цикл
                if ((int)chr == 27)
                    break;

                // Записываем символ в отображенную память,
                // доступную серверному процессу
                //КАК ПРАВИЛЬНО ЭТО СДЕЛАТЬ?
                lpFileMap = (IntPtr)chr;
                                
                Console.WriteLine("\nВы ввели  "+chr);
                Console.WriteLine("lpFileMap = {0}\n", lpFileMap.ToString());
                
                // Устанавливаем объект-событие в отмеченное
                // состояние
                SetEvent(hEvent);
            }

            // После завершения цикла переключаем оба события
            // в отмеченное состояние для отмены ожидания в
            // процессе отображения и для завершения этого процесса
            SetEvent(hEvent);
            SetEvent(hEventTermination);

            // Закрываем идентификаторы объектов-событий
            CloseHandle(hEvent);
            CloseHandle(hEventTermination);

            // Отменяем отображение файла
            UnmapViewOfFile(lpFileMap);

            // Освобождаем идентификатор созданного
            // объекта-отображения
            CloseHandle(hFileMapping);
            
           
        }
    }
}



ну вот вроде и всё, заранее спасибо smile  
PM MAIL   Вверх
Alexsar
Дата 12.6.2006, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: 2
Всего: 1



что никто не знает? smile  
PM MAIL   Вверх
mr.DUDA
Дата 14.6.2006, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Юзай Microsoft.ApplicationBlocks.MemoryMappedFile и всё получится. 


--------------------
user posted image
PM MAIL WWW   Вверх
Alexsar
Дата 17.6.2006, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: 2
Всего: 1



Microsoft.ApplicationBlocks.MemoryMappedFile-это библиотека такая в С#? 
PM MAIL   Вверх
mr.DUDA
Дата 19.6.2006, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Да, входит в состав бесплатного пакета Microsoft Enterprise Library for .NET 


--------------------
user posted image
PM MAIL WWW   Вверх
Alexsar
Дата 25.6.2006, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: 2
Всего: 1



Всем спасибо кому я запарил мозги, в особенности TO mr.DUDA  smile 
всё сделал с помощью pipe и айпишных функций
считаю, что  smile  
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0575 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.