Also das versenden klappt super (: Dafür nochmal ein dickes
DANKE
Jetzt habe ich versucht eine Pingfunktion einzubauen, die alle 2 Sekunden einen "ping" sendet der wiederum mit einem "OK" beantwortet wird. Das klappt auch super. Wenn der Server offline geht bemerkt der client das auch wie gewollt nach 5 Sekunden.
Jetzt habe ich allerdings dass Problem dass sobald ein 2. Client ins Spiel kommt, der Server das spinnen anfängt. Ich persönlich denke es liegt an der pingfunktion, kann es aber nicht wirklich zuordnen );
Als Fehler kommt das ein Pointer Null ist und zwar in der Funktion createPacket()
Ich gebe euch mal den Code... vielleicht ist die Umsetzung einfach idiotisch oder ihr könnt den Fehler finden (:
server:
Code: Alles auswählen
EnableExplicit
Structure user
name.s{32}
id.i
EndStructure
Structure packet
sender.user
receiver.user
type.s{8}
packetData.s{1000}
EndStructure
#version = "0.2"
Enumeration
#window
#statusbar
#chatServerID
#chatServerPort = 1337
EndEnumeration
Global exit = #False, clients
Global NewList clients.user()
Global server.user
With server
\id = -1
\name = "server"
EndWith
If Not InitNetwork()
MessageRequester("error","network error")
End
EndIf
Procedure removeClient(clientID) ;removes client by ID
ForEach clients()
If clients()\id = clientID
DeleteElement(clients())
EndIf
Next
EndProcedure
Procedure identifyClient(clientID) ;identifys client by ID
ForEach clients()
If clients()\id = clientID
ProcedureReturn @clients()
EndIf
ProcedureReturn #False
Next
EndProcedure
Procedure createPacket(*sender.user,*receiver.user, type.s, packetData.s)
Protected *packet.packet
*packet = AllocateMemory(SizeOf(packet))
If *packet
With *packet
\sender\id = *sender\id
\sender\name = *sender\name
\receiver\id = *receiver\id
\receiver\name = *receiver\name
\type = type
\packetData = packetData
EndWith
EndIf
ProcedureReturn *packet
EndProcedure
Procedure sendPacket(*packet.packet)
SendNetworkData(*packet\receiver\id,*packet,SizeOf(packet))
EndProcedure
Procedure clientLogin(loginClient) ;login procedure (thread)
Protected *packetBuffer.packet = AllocateMemory(SizeOf(packet))
clients+1
Repeat
ReceiveNetworkData(loginClient,*packetBuffer,SizeOf(packet))
Until *packetBuffer\type = "login"
StatusBarText(#statusbar,1,"clients: "+Str(clients))
AddElement(clients())
clients()\id = loginClient
clients()\name = *packetBuffer\sender\name
StatusBarText(#statusbar,0,"client logged in: "+*packetBuffer\sender\name)
*packetBuffer = createPacket(server,clients(),"clientID",Str(loginClient))
If *packetBuffer
sendPacket(*packetBuffer)
FreeMemory(*packetBuffer)
EndIf
EndProcedure
Procedure startChatServer(dummy) ;network-loop (thread)
Protected *sender.user, *receiver.user, *packetBuffer.packet = AllocateMemory(SizeOf(packet)), *oldpacket.packet = AllocateMemory(SizeOf(packet))
If CreateNetworkServer(#chatServerID,#chatServerPort,#PB_Network_TCP)
Repeat
Select NetworkServerEvent()
Case #PB_NetworkEvent_Connect
CreateThread(@clientLogin(),EventClient())
Case #PB_NetworkEvent_Data
If ReceiveNetworkData(EventClient(),*packetBuffer,SizeOf(packet))
If *packetBuffer <> *oldpacket
*oldpacket = *packetBuffer
Select *packetBuffer\type
Case "info"
Case "ping"
*sender = identifyClient(EventClient())
If *sender
*packetBuffer = createPacket(@server,*sender,"ping","OK")
sendPacket(*packetBuffer)
EndIf
Case "msg"
EndSelect
EndIf
EndIf
Case #PB_NetworkEvent_Disconnect
clients-1
StatusBarText(#statusbar,1,"clients: "+Str(clients))
removeClient(EventClient())
EndSelect
Delay(10)
Until exit
EndIf
CloseNetworkServer(#chatServerID)
exit = #True
EndProcedure
Procedure windowHandler() ;initializes the window and its eventlistener
If OpenWindow(#window,0,0,300,20,"networkserver ~ v"+#version,#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget)
If CreateStatusBar(#statusbar,WindowID(#window))
AddStatusBarField(225)
AddStatusBarField(75)
StatusBarText(#statusbar,1,"clients: 0")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
exit = #True
EndSelect
Until exit
EndIf
EndIf
EndProcedure
CreateThread(@startChatServer(),0)
windowHandler()
client:
Code: Alles auswählen
EnableExplicit
Structure user
name.s{32}
id.i
EndStructure
Structure packet
sender.user
receiver.user
type.s{8}
packetData.s{1000}
EndStructure
#version = "0.2"
Enumeration
#Window
#Send
#Console
#Input
#List
#Status
#chatServerID
#chatServerPort = 1337
EndEnumeration
Global exit = #False, chatConnection, IP.s = "127.0.0.1", initialized = #False
Global user.user, server.user
Repeat
user\name = InputRequester("please enter a nickname","(max. 32 signs, otherwise your name will be cut)","")
Until user\name
server\name = "server"
If Not InitNetwork()
MessageRequester("Error","Network error")
End
EndIf
Procedure sendPacket(*packet.packet)
SendNetworkData(*packet\receiver\id,*packet,SizeOf(packet))
EndProcedure
Procedure createPacket(*sender.user,*receiver.user, type.s, packetData.s)
Protected *packet.packet
*packet = AllocateMemory(SizeOf(packet))
If *packet
With *packet
\sender\id = *sender\id
\sender\name = *sender\name
\receiver\id = *receiver\id
\receiver\name = *receiver\name
\type = type
\packetData = packetData
EndWith
EndIf
ProcedureReturn *packet
EndProcedure
Procedure windowHandler() ;initializes the window and its eventlistener
Protected *packetBuffer = AllocateMemory(SizeOf(packet))
OpenWindow(#Window, 5, 5, 507, 260, "network client ~ v"+#version+" "+user\name, #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
AddKeyboardShortcut(#Window,#VK_RETURN,#Send)
EditorGadget(#Console, 10, 10, 360, 180, #PB_Editor_ReadOnly)
StringGadget(#Input, 10, 200, 360, 20, "")
ButtonGadget(#Send, 280, 230, 90, 20, "Send")
ListViewGadget(#List, 390, 10, 100, 210)
TextGadget(#Status, 10, 230, 260, 20, "")
EnableGadgetDrop(#Input,#PB_Drop_Files,#PB_Drag_Copy)
initialized = #True
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #Send
If GetGadgetText(#Input)
*packetBuffer = createPacket(@user,@server,"msg",GetGadgetText(#Input))
If *packetBuffer
sendPacket(*packetBuffer)
EndIf
EndIf
EndSelect
Case #PB_Event_CloseWindow
exit = #True
EndSelect
Until exit
EndProcedure
Procedure startChatConnection(*connectionIP.s) ;starts the networloop and handles events (thread)
Protected connectionIP.s = *connectionIP, eventclient, *packetBuffer.packet = AllocateMemory(SizeOf(packet))
Protected timeout, pingOK = 1
server\id = OpenNetworkConnection(connectionIP,#chatServerPort,#PB_Network_TCP)
Repeat : Delay(10) : Until initialized
If server\id
*packetBuffer = createPacket(@user,@server,"login","") ;sending of the login-string
sendPacket(*packetBuffer)
If ReceiveNetworkData(server\id,*packetBuffer,SizeOf(packet)) ;receiving clientID
If *packetBuffer\type = "clientID"
user\id = Val(*packetBuffer\packetData)
SetGadgetText(#Console,"Login successful ID: "+Str(user\id))
Repeat ;network-slope
Select NetworkClientEvent(server\id)
Case #PB_NetworkEvent_Data
If ReceiveNetworkData(server\id,*packetBuffer,SizeOf(packet))
Select *packetBuffer\type ;getting packet-type
Case "info"
Case "ping"
If *packetBuffer\packetData = "OK"
pingOK = 1
timeout = 0
EndIf
Case "msg"
SetGadgetText(#Console,*packetBuffer\sender\name+": "+*packetBuffer\packetData)
EndSelect
EndIf
EndSelect
If Not timeout
timeout = ElapsedMilliseconds()
Else
If ElapsedMilliseconds()-timeout > 2000 And pingOK = 1
*packetBuffer = createPacket(@user,@server,"ping","")
sendPacket(*packetBuffer)
pingOK = 0
EndIf
If ElapsedMilliseconds()-timeout > 5000
MessageRequester("error","server timed out")
exit = #True
EndIf
EndIf
Delay(10)
Until exit
Else
MessageRequester("error","login failed")
exit = #True
EndIf
Else
MessageRequester("error","server doesn't answer")
exit = #True
EndIf
Else
MessageRequester("error","server unavailable")
exit = #True
EndIf
CloseNetworkServer(#chatServerID)
EndProcedure
CreateThread(@startChatConnection(),@ip)
windowHandler()
Danke im Vorraus (:
deify