PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Send/ReceiveNetworkData многократное использование


Send/ReceiveNetworkData многократное использование

Сообщений 1 страница 22 из 22

1

Здравствуйте, у меня появился новый вопрос, ни как не могу понять или придумать алгоритм.
Есть клиент и сервер, сервер передает данные клиент принимает, но как сделать чтобы сервер мог отправлять допустим 5 разных данных при помощи (SendNetworkData) а клиент принимать (ReceiveNetworkData) и на оборот, чтобы эти функции не путались и не перехватывали друг друга. Как им присвоить идентификаторы?

Отредактировано Racer (15.09.2013 14:35:52)

0

2

Описание.

Через сеть вы передаете и принимаете массив (поток) данных и в них должны быть специальные метки чтобы можно было этот массив разобрать на приемной стороне. Среди таких моток должны быть как минимум, команда (тип данных) и длина пакета с данными. Таким образом, при приеме массива данных из сети, будет информация, во первых о типе пакета, необходимая для его правильной обработки, а во вторых, длина пакета, необходимая чтобы точно знать каков его размер. Это можно описать примерно такой структурой (ЯП в данном случае не имеет значения).

Код:
Structure NetPacket_Header 
  Size.u  ; 2 байта.
  Type.u  ; 2 байта.
EndStructure

Эта структура является заголовком пакета и должна быть в его начале, и за ней следуют данные. Поле Size определяет размер пакета. В данном случае, его размер не может превышать 64 КБ, но если увеличить размер поля до 4-ёх байт, то появится возможность передавать пакеты имеющие размер до 4 ГБ. Но это нежелательно, поскольку если потеряется пакет не большого размера, то его быстрее можно будет повторно отправить. Поле Type определяет тип пакета (команду), необходимую для правильной обработки пакета на приемной стороне.
Если протокол реализован поверх UDP, или другого низкоуровневого протокола, то не помешает добавить так же поле с контрольной суммой пакета, чтобы удостоверится в целостности данных.

Есть еще один момент, на который необходимо обратить внимание. Пакет может быть принят не за один раз (вызов принимающей функции из сети) или наоборот, за раз может быть принято несколько пакетов, причем последний из них может быть принят не полностью. Поэтому так же необходим промежуточный буфер, в который будут записываться все данные, принимаемые из сети, а затем, по мере получения целых пакетов, уже обрабатываться.

Реализация в коде (сервер и клиент) всего вышенаписанного. Для примера, реализованы две команды:

Код:
#NetPacketType_EndProg ; Завершить работу клиента.
#NetPacketType_Data    ; Данные.

http://purebasic.info/phpBB2/viewtopic.php?t=3035

Сервер.

Код:
Structure NetBuff_Param 
  *Buff 
  Len.l 
  Pos.l 
EndStructure 

EnableExplicit 

Procedure NetBuff_ReallocateMemory(*Buff.NetBuff_Param, AddBytes) ; Нужно ли увеличить память под данные, принимаемые от пира? 
  Protected Len, Pos, NewLen, *Point 
  Protected *NewPoint, i 
  
  Len = *Buff\Len 
  Pos = *Buff\Pos 
  *Point = *Buff\Buff 
  
  If AddBytes>0 
    NewLen = 0 
    If Pos>Len Or Len-Pos < AddBytes Or *Point=0; Нужно изменить (увеличить) размер памяти. 
      NewLen = Len+AddBytes+100 
    ElseIf Len-Pos > AddBytes+400 ; Памяти выдленено слишком много и надо уменьшить. 
      NewLen = AddBytes+Pos+80 
    EndIf 
    
    If NewLen > 0 
      For i=1 To 4 
        *NewPoint = ReAllocateMemory(*Point, NewLen) 
        If *NewPoint 
          *Buff\Buff = *NewPoint 
          *Buff\Len = NewLen 
          If *Buff\Len>NewLen 
            *Buff\Len=NewLen 
          EndIf 
          Len = NewLen 
          Break 
        Else 
          Delay(4) 
        EndIf 
      Next i 
    EndIf 
    
  EndIf 
  
  ProcedureReturn Len 
EndProcedure 


Procedure NetBuff_AddMem(*Buff.NetBuff_Param, *Mem, AddBytes) ; Добавление принятых жанных от пира, в память еще необработанных сообщений. 
  Protected NewLen 
  
  NewLen=NetBuff_ReallocateMemory(*Buff, AddBytes) ; Выделение памяти 
  If NewLen>0 And *Buff\Len >= AddBytes+*Buff\Pos ; Память выделена 
    CopyMemory(*Mem, *Buff\Buff+*Buff\Pos, AddBytes) 
    *Buff\Pos + AddBytes 
  EndIf 
  
EndProcedure 


Procedure NetBuff_DelMem(*Buff.NetBuff_Param, DelBytes) ; Удаление принятых данных от пира, из памяти после успешной обработки сообщения. 
  
  If *Buff\Buff 
    If *Buff\Pos <= DelBytes 
      *Buff\Pos = 0 
    Else 
      If *Buff\Pos>DelBytes 
        MoveMemory(*Buff\Buff+DelBytes, *Buff\Buff, *Buff\Pos-DelBytes) ; 
      EndIf 
      *Buff\Pos - DelBytes 
      If *Buff\Pos<0 
        *Buff\Pos=0 
      EndIf 
    EndIf 
  EndIf 
  
EndProcedure 


Enumeration 
  #NetPacketType_EndProg 
  #NetPacketType_Data 
EndEnumeration 

Structure NetPacket_Header 
  Size.u 
  Type.u 
EndStructure 

Structure NetPacket_EndData 
  Header.NetPacket_Header 
EndStructure 

Structure NetPacket_Data 
  Header.NetPacket_Header 
  Buff.a[0] 
EndStructure 


Procedure Net_InData(Connect, *Point, Size, *BuffInfo.NetBuff_Param) 
  Protected InBytes, *Header.NetPacket_Header 
  Protected Result 
  
  NetBuff_AddMem(*BuffInfo, *Point, Size) 
  Result = #False 
  
  Repeat 
    
    If *BuffInfo\Pos>=SizeOf(NetPacket_Header) 
      
      *Header = *BuffInfo\Buff 
      
      If *BuffInfo\Pos >= *Header\Size 
        
        Select *Header\Type 
          Case #NetPacketType_EndProg 
            Protected *EndData.NetPacket_EndData = *BuffInfo\Buff 
            
            Result = #True 
            
            NetBuff_DelMem(*BuffInfo, *Header\Size) 
            
          Case #NetPacketType_Data 
            Protected *Data.NetPacket_Data = *BuffInfo\Buff 
            
            Debug PeekS(@*Data\Buff[0], *Data\Header\Size-OffsetOf(NetPacket_Data\Buff)) 
            
            NetBuff_DelMem(*BuffInfo, *Header\Size) 
            
            
        EndSelect 
        
      Else 
        Break 
      EndIf 
      
    EndIf 
    
  Until *BuffInfo\Pos < SizeOf(NetPacket_Header) 
  
  ProcedureReturn Result 
  
EndProcedure 

InitNetwork() 

Define Connect = OpenNetworkConnection("127.0.0.1", 2222, #PB_Network_TCP) 
If Connect 
  
  Define *Point = AllocateMemory(65536) 
  If *Point 
    Define BuffInfo.NetBuff_Param\Buff = AllocateMemory(10) 
    BuffInfo\Len=10 
    BuffInfo\Pos=0 
    If BuffInfo\Buff 
      
      Repeat 
        Define NetEvent = NetworkClientEvent(Connect) 
        If NetEvent = #PB_NetworkEvent_Data 
          Define InBytes = ReceiveNetworkData(Connect, *Point, 65536) 
          If Net_InData(Connect, *Point, InBytes, @BuffInfo) 
            Break 
          EndIf 
        Else 
          Delay(10) 
        EndIf 
      ForEver 
      
      CloseNetworkConnection(Connect) 
      
      FreeMemory(BuffInfo\Buff) 
    EndIf 
    FreeMemory(*Point) 
  EndIf 
Else 
  Debug "Нет связи" 
EndIf

Клиент.

Код:
Enumeration 
  #NetPacketType_EndProg 
  #NetPacketType_Data 
EndEnumeration 

Structure NetPacket_Header 
  Size.u 
  Type.u 
EndStructure 

Structure NetPacket_EndData 
  Header.NetPacket_Header 
EndStructure 

Structure NetPacket_Data 
  Header.NetPacket_Header 
  Buff.a[0] 
EndStructure 

;Header.NetPacket_Header 
EndData.NetPacket_EndData 


Procedure Send(Connect, String.s) 
  NetPacket_Data.NetPacket_Data 
  
  NetPacket_Data\Header\Size = SizeOf(NetPacket_Header)+StringByteLength(String) 
  NetPacket_Data\Header\Type = #NetPacketType_Data 
  
  SendNetworkData(Connect, @NetPacket_Data\Header, SizeOf(NetPacket_Header)) 
  SendNetworkData(Connect, @String, StringByteLength(String)) 
  
EndProcedure 

If InitNetwork() = 0 
  MessageRequester("Error", "Can't initialize the network !", 0) 
  End 
EndIf 

Port = 2222 
*Buffer = AllocateMemory(1000) 

If CreateNetworkServer(0, Port) 
  
  Repeat 
    
    SEvent = NetworkServerEvent() 
    
    If SEvent 
      
      ClientID = EventClient() 
      
      Select SEvent 
          
        Case #PB_NetworkEvent_Connect 
          
          Send(ClientID, "Первая строка") 
          Send(ClientID, "Еще строка") 
          Send(ClientID, "Строка № 3") 
          Send(ClientID, "Больше нет строк") 
          
          EndData\Header\Size = SizeOf(NetPacket_Header) 
          EndData\Header\Type = #NetPacketType_EndProg 
          SendNetworkData(ClientID, @EndData, SizeOf(NetPacket_Header)) 
          
        Case #PB_NetworkEvent_Disconnect 
          MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has closed the connection...", 0) 
          Quit = 1 
          
      EndSelect 
    EndIf 
    
  Until Quit = 1 
  
  MessageRequester("PureBasic - Server", "Click to quit the server.", 0) 
  
  CloseNetworkServer(0) 
Else 
  MessageRequester("Error", "Can't create the server (port in use ?).", 0) 
EndIf 


End

0

3

Тяжеловато, ну что же буду разбираться, спасибо. Я думал будет по проще.

0

4

Это универсальный метод и возможно в коде (он взят из исходника торрент-климента) есть ненужное для конкретного случая.
Для мелких пакетов (пара байт) которые редко отправляются, можно исключить буферизацию и тем самым упростив код. А если пакет всего один и всегда одинакового размера, то становится ненужным, указывание типа пакета и его размера.

0

5

А можно упрощенную версию пожалуйста? Я в этих процедурах и структурах загрузну на очень долго...
Да кстати, дабы не создавать новую тему, хотел спросить, что случилось с базой вирусов сигнатур у нода? почему всё 3D приложения детектятся как вирус?

Анализ 1
Анализ 2

http://s4.uploads.ru/t/N6CwP.jpg

Вот сам код:

Код:
Define.f KeyX, KeyY, MouseX, MouseY

ExamineDesktops()
Result1 = DesktopWidth(0)
Result2 = DesktopHeight(0)
Result3 = DesktopDepth(0)

If InitEngine3D()
Add3DArchive("Models", #PB_3DArchive_FileSystem)
Parse3DScripts()
InitSprite()
InitKeyboard()
InitMouse()

AntialiasingMode(#PB_AntialiasingMode_x6)
OpenScreen(Result1, Result2, Result3, "123", #PB_Screen_WaitSynchronization, RefreshRate)

UseJPEGImageDecoder()
LoadSprite(100,"OWGELogo.jpg")
RenderWorld()
DisplaySprite(100, 430,300)
FlipBuffers()
Delay(3000)
  
CreateLight(0, RGB(255, 255, 255), -10, 40, 20, #PB_Light_Point)
CreateCamera(0,0,0,100,100)
LoadMesh(3, "1.mesh")
CreateEntity(3, MeshID(3), #PB_Material_None, 0, 0, 0)
ScaleEntity(3, 5, 5, 5)

Repeat
ExamineMouse()
MouseX = -MouseDeltaX() * 2 * 0.05
MouseY = -MouseDeltaY() * 2 * 0.05

If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -40
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = 40 
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -40
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = 40
Else
KeyY = 0
EndIf
EndIf
            
RotateCamera(0, MouseY, MouseX, 0, #PB_Relative)
MoveCamera  (0, KeyX, 0, KeyY)
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
Else
MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf
End

Если создать приложение с использованием стартера Screen3DRequester.pb тогда нормально, а если без него - вирус.

Отредактировано Racer (15.09.2013 20:33:46)

0

6

Дайте угадаю, у вас Аваст? Без отладчика должно всё отлично работать

0

7

Никита, у меня нод, и с отладчиком, и без него ошибка/вирус.

0

8

Racer написал(а):

А можно упрощенную версию пожалуйста?

Что именно упростить?

Упрощенная в справке.
Сервер. http://purebasic.com/documentation/Exam … er.pb.html
Клиент. http://purebasic.com/documentation/Exam … nt.pb.html

0

9

Пётр написал(а):

Для мелких пакетов (пара байт) которые редко отправляются, можно исключить буферизацию и тем самым упростив код. А если пакет всего один и всегда одинакового размера, то становится ненужным, указывание типа пакета и его размера.

Я бы так не рисковал. Ведь что угодно между сервером и клиентом может порезать пакеты, хоть по одному байту.

0

10

Paranoia написал(а):

Я бы так не рисковал.

Оно то так, но нужно было что-то по проще.

0

11

Я извиняюсь, но что делать с 3d приложениями, почему их стал блокировать нод?! Раньше всё бло ок.

0

12

Нод не блокирует примеры из папки с PB.
Случайно не используется библиотека, типа Droopy?

0

13

Компилировал на чистой оф. версии свой код - вирус.  Но я не подключаю Screen3DRequester.pb. раньше всё работало нормально, это сейчас что-то случилось..

0

14

Напишите в тех. поддержку нода и приложите скомпилированную программу.
Они или напишут причину или исключат прогу из баз.

0

15

Ага, у них в поддержке, нельзя даже файл прикрепить, я выяснил, ругается на функцию LoadMesh(). причем это бред, один код компилит нормально, а второй как вирус.

0

16

Racer написал(а):

Ага, у них в поддержке, нельзя даже файл прикрепить, я выяснил, ругается на функцию LoadMesh(). причем это бред, один код компилит нормально, а второй как вирус.

К письму нельзя файл прикрепить?

Отправить запрос в техническую поддержку можно написав электронное письмо на адрес support@esetnod32.ru или заполнив форму, приведенную ниже. Ответ будет выслан на контактный адрес электронной почты.

0

17

Письмо написал, но всё же я не понимаю, почему стандартные примеры работают нормально, и прочие некоторые мои старые работы, а всё что пытаюсь написать сейчас - вирус.
пожалуйста, проверьте кто-то данный код, что в нем такого, я не могу понять, раньше всё чудесно работало. переустанавливал винду, антивирус, среду Pure basicа - безтолку.
Скомпилированный архив - скачать

http://libertyfile.3dn.ru/vip-files/photo.jpg

Вот сам код:

Код:
Define.f KeyX, KeyY, MouseX, MouseY
#SCREENWIDTH = 1440
#SCREENHEIGHT = 900

InitEngine3D()
InitKeyboard()
InitMouse()
InitSprite()
InitSprite3D()

AntialiasingMode(#PB_AntialiasingMode_x6)
OpenScreen(#SCREENWIDTH, #SCREENHEIGHT, 32, "Test", #PB_Screen_WaitSynchronization)


CreateCube(11,50)
CreateEntity(11, MeshID(11), #PB_Material_None, 0, 0, 0)

CreateLight(0, RGB(255, 255, 255), -10, 40, 20, #PB_Light_Point)
CreateCamera(0,0,0,100,100)

Repeat
RenderWorld()
FlipBuffers()

If ExamineMouse()
MouseX = -MouseDeltaX() * 2 * 0.05
MouseY = -MouseDeltaY() * 2 * 0.05
EndIf
            
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -22
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = 22
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -22
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = 22
Else
KeyY = 0
EndIf
EndIf

RotateCamera(0, MouseY, MouseX, 0, #PB_Relative)
MoveCamera  (0, KeyX, 0, KeyY)
Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
End

Отредактировано Racer (23.09.2013 23:11:57)

0

18

Хорошая поддержка у них, написал 4 дня назад, гни ответа, ни привета. Хана кароче 3D составляющей, сегодня пробовал на чужом компьютере, тоже под нодом32, но только старая версия, также детектится, уже занесено в сигнатуры антивирусов...

0

19

Racer написал(а):

Вот сам код

Нод молчит.

0

20

А вы комплировали, или создали приложение?  При компиляции у меня тоже всё ок.

0

21

Петр, ответьте пожалуйста, мне очень важно знать!

0

22

Запускал в IDE с отладчиком.
Без отладчика - NOD32 блокирует прогу. Наверное стоит об этом написать на официальном форуме приложив код. Путь авторы PB разбираются с этим.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Send/ReceiveNetworkData многократное использование