powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Одна прога пишет строку, другая читает(если хочет) но не удаляет
12 сообщений из 12, страница 1 из 1
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402710
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Грубо.
Есть несколько аккаунтов, имена известны обоим сторонам.
У аккаунта есть "состояния", например: Trying, Registered, Error(номер, описание)

Сервер генерирует эту строку "состояния" для аккаунта в какие-то моменты. Должен ее куда-то записать.

А клиент должен эту строку прочитать (чтоб на себе отобразить).
При этом "состояние" генерируется сервером не непрерывно,
да и клиент может быть не запущен, а потом взяли-запустили дабы посмотреть это самое "состояние".

Здесь кроме таймера на клиенте ничего умного в голову не приходит.

Вопрос где хранить.

В старой проге сервер сохранял файл "имя_аккаунта", внутрь писал "состояние", сервер остановили - файл убился.
Клиент когда ему надо, идет и читает этот файл (по таймеру, дабы изменения отслеживать).

С файлами надежно (динамика несильная), но хочется чего-то посолиднее.
Вот это может? Правильно мыслю?
Creating Named Shared Memory

М.б. в .Net самом чего-то свое есть?

Mailslot не пойдет, он читает и удаляет. Надо чтоб сервер писал, когда есть изменение (клиент на момент изменения не обязательно запущен), а клиент читал когда ему надо (там уже может лежать инфа, на момент его запуска).
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402718
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

СУБД рассматривал?
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402722
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

Ну ты скажешь тоже. СУБД. Речь идет о SIP-аккаунтах. Мне надо отобразить: зарегистрирован/не зарегистрирован. Регистраций может быть несколько. user@server:[port] -однозначно определяет аккаунт, поэтому это сочетание можно присвоить имени файла (или mailslot-а, который здесь неудобен), а "внутрь" записать значение(текст), т.е. зарегистрирован или не зарегистрирован.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402736
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77М.б. в .Net самом чего-то свое есть?
Дуплексный WCF-сервис.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402763
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

СУБД может быть очень простой и легковесной

Sip account с состоянием вполне может в СУБД храниться
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402764
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Дмитрий77Сервер генерирует эту строку "состояния" для аккаунта в какие-то моменты. Должен ее куда-то записать.
А зачем куда-то писать? По-моему достаточно, что бы сервер отвечал заинтересованным клиентам

Сон Веры ПавловныДмитрий77М.б. в .Net самом чего-то свое есть?
Дуплексный WCF-сервис.
Не уверен, что нужен именно дуплексный, но WCF-сервис поднять надо.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402768
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZeroMQ , открой сокет ZMQ_PUB и сыпь все туда. Будут подписчики, получат, не будет - просто потеряется.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402776
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чет советы все мудреные.
У меня вот чего пока теста ради получилось (на базе моей же ссылки в первом посте):

Сервер:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
  Dim hMapFile As IntPtr

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Dim SA As SECURITY_ATTRIBUTES
    hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, SA, PAGE_READWRITE, 0, 256, "sip:100@192.168.1.1:5068") '"MyFileMappingObject"
    If hMapFile = IntPtr.Zero Then
      Debug.Print("CreateFileMapping Error " & RaiseAPIError())
      Exit Sub
    End If
  End Sub

  Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    CloseHandle(hMapFile)
  End Sub

  Private Sub ButtonPut_Click(sender As Object, e As EventArgs) Handles ButtonPut.Click
    Dim pBuf As IntPtr
    pBuf = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 256)
    If pBuf = IntPtr.Zero Then
      Debug.Print("MapViewOfFile Error " & RaiseAPIError())
      CloseHandle(hMapFile)
      Exit Sub
    End If

    Dim t_bData As Byte() = System.Text.Encoding.Unicode.GetBytes(TextBoxPut.Text & Chr(0))
    Marshal.Copy(t_bData, 0, pBuf, t_bData.Length)

    UnmapViewOfFile(pBuf)
  End Sub



Клиент:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
 Private Sub ButtonTake_Click(sender As Object, e As EventArgs) Handles ButtonTake.Click
    Dim hMapFile As IntPtr
    Dim pBuf As IntPtr

    hMapFile = OpenFileMapping(SECTION_MAP_READ, False, "sip:100@192.168.1.1:5068")
    If hMapFile = IntPtr.Zero Then
      Debug.Print("CreateFileMapping Error " & RaiseAPIError())
      Exit Sub
    End If

    pBuf = MapViewOfFile(hMapFile, SECTION_MAP_READ, 0, 0, 256)
    If pBuf = IntPtr.Zero Then
      Debug.Print("MapViewOfFile Error " & RaiseAPIError())
      CloseHandle(hMapFile)
      Exit Sub
    End If

    Dim bytData As Byte() = New Byte(255) {}
    Marshal.Copy(pBuf, bytData, 0, 256)
    MsgBox(System.Text.Encoding.Unicode.GetString(bytData, 0, 256).Trim())

    UnmapViewOfFile(pBuf)
    CloseHandle(hMapFile)

  End Sub



Причесать, все отлично.
Но вот вижу проблемы.

С клиентом проблем нет. Он знает имя "sip:100@192.168.1.1:5068", вскрывает "файл" и читает. Ну и закрывает handle сразу.

А вот с "сервером" вижу траблы. Т.е. открыть, положить и закрыть я не могу, тогда "файл" сдохнет.
(с файлом на диске в этом плане удобнее)
Поэтому вместо чтоб обращаться по имени "sip:100@192.168.1.1:5068" когда что-то меняется
я должен тянуть сквозь всю прогу пару ("sip:100@192.168.1.1:5068", hMapFile),
в общем случае несколько пар по числу регистраций.
Иногда надо менять эти пары динамически.
Ну т.е. понятно что когда делаю Register, надо hMapFile создать, когда UnRegister -грохнуть, меняется статус - класть туда строку.

Плюс еще Global\ мне поднять не удалось (по крайне мере под юзером.)
Под админом SeCreateGlobalPrivilege вроде ставятся.

У меня сервером будет NT Service, поэтому нужно Global\
там думаю получится,
но скорее всего еще придется возиться с SA (в принципе тоже понятно как).

В общем везде гимор, м.б. файлы оставить и не париться. 10 лет никто не жаловался.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402802
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Дмитрий77Причесать, все отлично.
Я так понял, что это работает только если и клиент и сервер находятся на одной машине.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402808
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cat2Я так понял, что это работает только если и клиент и сервер находятся на одной машине.
Надеюсь, что на соседнюю не ходит (в том числе с \Global).
Я пока user-user(тот же) пробовал без \Global. Там еще SA понадобится.
Под юзером без админа у меня \Global не получился.
Ну вообще зараза, потому что будут проблемы при тестировании под юзером если положу global.
А под юзером тестировать удобнее.
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402813
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну а с парой ("name", hMapFile) в принципе обычная VB-коллекция справится :
Код: vbnet
1.
    Dim mm As New Collection
...
Рейтинг: 0 / 0
Одна прога пишет строку, другая читает(если хочет) но не удаляет
    #39402980
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, у меня все получилось.
Вот такой причесанный модуль:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
Imports System.Runtime.InteropServices

Module m_NamedSharedMemory

  'Creating Named Shared Memory
  'https://msdn.microsoft.com/en-US/library/windows/desktop/aa366551(v=vs.85).aspx

  'Memory Management Functions

  'flProtect - Specifies the page protection of the file mapping object. All mapped views of the object must be compatible with this protection.
  Public Const PAGE_READWRITE As Integer = &H4

  Public Declare Unicode Function CreateFileMapping Lib "kernel32" _
   Alias "CreateFileMappingW" (ByVal hFile As IntPtr, _
   ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal flProtect As Integer, _
   ByVal dwMaximumSizeHigh As Integer, ByVal dwMaximumSizeLow As Integer, _
   ByVal lpName As String) As IntPtr

  'dwDesiredAccess - The type of access to a file mapping object, which determines the protection of the pages.
  Public Const FILE_MAP_WRITE = &H2
  Public Const FILE_MAP_READ = &H4

  Public Declare Unicode Function OpenFileMapping Lib "kernel32" _
   Alias "OpenFileMappingW" (ByVal dwDesiredAccess As Integer, _
   ByVal bInheritHandle As Boolean, _
   ByVal lpName As String) As IntPtr
  Public Declare Unicode Function MapViewOfFile Lib "kernel32" (ByVal hFileMappingObject As IntPtr, _
   ByVal dwDesiredAccess As Integer, _
   ByVal dwFileOffsetHigh As Integer, ByVal dwFileOffsetLow As Integer, _
   ByVal dwNumberOfBytesToMap As IntPtr) As IntPtr
  Public Declare Function UnmapViewOfFile Lib "kernel32" (ByVal lpBaseAddress As IntPtr) As Boolean

  'Handle and Object Functions
  Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Boolean

  Public Function CreateMapFile(ByVal f_name As String, Optional ByVal FullAccess As Boolean = False) As IntPtr
    Dim SA As SECURITY_ATTRIBUTES
    If FullAccess Then SA = CreateMailslotSecurityFullAccess()
    CreateMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, SA, PAGE_READWRITE, 0, 256, f_name)
    If CreateMapFile = IntPtr.Zero Then
      'Debug.Print("CreateFileMapping Error " & RaiseAPIError())
    End If
  End Function

  Public Sub CloseMapFile(ByVal hMapFile As IntPtr)
    If hMapFile <> IntPtr.Zero Then CloseHandle(hMapFile)
  End Sub

  Public Sub WriteMapFileString(ByVal hMapFile As IntPtr, ByVal the_str As String)
    If hMapFile = IntPtr.Zero Then Exit Sub
    Dim pBuf As IntPtr
    pBuf = MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 256)
    If pBuf = IntPtr.Zero Then
      'Debug.Print("MapViewOfFile Error " & RaiseAPIError())
      Exit Sub
    End If

    Dim t_bData As Byte() = System.Text.Encoding.Unicode.GetBytes(the_str & Chr(0))
    Marshal.Copy(t_bData, 0, pBuf, t_bData.Length)

    UnmapViewOfFile(pBuf)
  End Sub

  Public Function ReadMapFileString(ByVal f_name As String) As String
    ReadMapFileString = ""

    Dim hMapFile As IntPtr
    Dim pBuf As IntPtr

    hMapFile = OpenFileMapping(FILE_MAP_READ, False, f_name)
    If hMapFile = IntPtr.Zero Then
      'Debug.Print("OpenFileMapping Error " & RaiseAPIError())
      Exit Function
    End If

    pBuf = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 256)
    If pBuf = IntPtr.Zero Then
      'Debug.Print("MapViewOfFile Error " & RaiseAPIError())
      CloseHandle(hMapFile)
      Exit Function
    End If

    Dim bytData As Byte() = New Byte(255) {}
    Marshal.Copy(pBuf, bytData, 0, 256)
    Dim the_str = System.Text.Encoding.Unicode.GetString(bytData, 0, 256)
    If InStr(the_str, Chr(0)) > 0 Then
      the_str = Strings.Left(the_str, InStr(the_str, Chr(0)) - 1)
    End If
    ReadMapFileString = the_str

    UnmapViewOfFile(pBuf)
    CloseHandle(hMapFile)

  End Function

End Module


К нему любимая универсальная функция CreateMailslotSecurityFullAccess() As SECURITY_ATTRIBUTES
годящаяся на все случаи жизни (Mailslot, Event и т.п.)
смысл, что объект доступен для всех и вся
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  Public Function CreateMailslotSecurityFullAccess() As SECURITY_ATTRIBUTES
    ' Define the SDDL for the security descriptor. 
    'DACL + OBJECT_INHERIT_ACE/CONTAINER_INHERIT_ACE + GENERIC_ALL (полный доступ) + SECURITY_WORLD_RID (группа "EveryOne")
    Dim sddl As String = "D:(A;OICI;GA;;;WD)"

    Dim pSecurityDescriptor As IntPtr
    Dim sa As New SECURITY_ATTRIBUTES
    If ConvertStringSecurityDescriptorToSecurityDescriptor(sddl, SDDL_REVISION_1, pSecurityDescriptor, IntPtr.Zero) Then
      sa.nLength = Marshal.SizeOf(sa)
      sa.lpSecurityDescriptor = pSecurityDescriptor
      sa.bInheritHandle = False
    End If

    Return sa
  End Function



Global\ требует SeCreateGlobalPrivilege для создающего "shared file" процесса, что по умолчанию доступно для NT Service (мой случай), либо для админа (сойдет для тестирования).
Для NT Service в обязательном порядке лепим CreateMailslotSecurityFullAccess, чтоб клиент под юзером мог читать инфу.

Ну а в моем случае реализация такая:

Сервер
при регистрации аккаунта создаем "shared file" и запихиваем hMapFile в коллекцию с ключем "имя_аккаунта"
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
  Dim colRegStatus As New Collection 'ключи - имена SIP-аккаунтов, значения - соответствующие им hMapFile
...
              'создаем "файл" и добавляем его в коллекцию
              Dim f_name As String = "Global\MyProgaName:sip:" & .m_UserName & "@" & .m_server 'имя "файла"
              If colRegStatus.Contains(f_name) = False Then
                colRegStatus.Add(CreateMapFile(f_name, True), f_name) ' True==FullAccess
              End If


При изменении статуса пишем его в "файл":
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
    If (Strings.Left(reg_status.m_serverName, 4) = "sip:") Then
      Dim f_name As String = "Global\MyProgaName:" & Replace(reg_status.m_serverName, ";transport=tcp", "") 'имя "файла"
      If txt_reg_status = "Unregistered" Then
        If colRegStatus.Contains(f_name) Then
          CloseMapFile(colRegStatus(f_name))
          colRegStatus.Remove(f_name)
        End If
      Else
        If colRegStatus.Contains(f_name) Then _
         WriteMapFileString(colRegStatus(f_name), txt_reg_status)
      End If
    End If


Перед закрытием "сервера" закрываем все "файлы" и грохаем коллекцию, хотя оно и так все убьется, но аккуратность не повредит
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
  Private Sub frm1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
...
    'удаляем все "файлы" с информацией о sip-регистрации
    For Each colItem As Object In colRegStatus
      CloseMapFile(colItem)
    Next colItem
    colRegStatus.Clear()



Клиент
(здесь вообще все просто)
Код: vbnet
1.
2.
3.
4.
5.
    For i As Integer = 0 To n - 1
      Dim f_name As String = "Global\MyProgaName:sip:" & FormConfig.ListViewSipRegister.Items(i).Name 'имя "файла"
      temp = ReadMapFileString(f_name)
      If Strings.Len(temp) > 0 Then
        '... отображаем статус
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Одна прога пишет строку, другая читает(если хочет) но не удаляет
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]