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

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

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

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

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

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

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

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

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

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

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

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

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

Сон Веры ПавловныДмитрий77М.б. в .Net самом чего-то свое есть?
Дуплексный WCF-сервис.
Не уверен, что нужен именно дуплексный, но WCF-сервис поднять надо.
...
Рейтинг: 0 / 0
11.02.2017, 20:05
    #39402768
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одна прога пишет строку, другая читает(если хочет) но не удаляет
ZeroMQ , открой сокет ZMQ_PUB и сыпь все туда. Будут подписчики, получат, не будет - просто потеряется.
...
Рейтинг: 0 / 0
11.02.2017, 20:55
    #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
11.02.2017, 21:42
    #39402802
Cat2
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одна прога пишет строку, другая читает(если хочет) но не удаляет
Дмитрий77Причесать, все отлично.
Я так понял, что это работает только если и клиент и сервер находятся на одной машине.
...
Рейтинг: 0 / 0
11.02.2017, 21:54
    #39402808
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одна прога пишет строку, другая читает(если хочет) но не удаляет
Cat2Я так понял, что это работает только если и клиент и сервер находятся на одной машине.
Надеюсь, что на соседнюю не ходит (в том числе с \Global).
Я пока user-user(тот же) пробовал без \Global. Там еще SA понадобится.
Под юзером без админа у меня \Global не получился.
Ну вообще зараза, потому что будут проблемы при тестировании под юзером если положу global.
А под юзером тестировать удобнее.
...
Рейтинг: 0 / 0
11.02.2017, 21:59
    #39402813
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Одна прога пишет строку, другая читает(если хочет) но не удаляет
Ну а с парой ("name", hMapFile) в принципе обычная VB-коллекция справится :
Код: vbnet
1.
    Dim mm As New Collection
...
Рейтинг: 0 / 0
12.02.2017, 16:33
    #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
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Одна прога пишет строку, другая читает(если хочет) но не удаляет / 12 сообщений из 12, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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