Chat (Linked List) Frage

Anfängerfragen zum Programmieren mit PureBasic.
kiki
Beiträge: 155
Registriert: 06.05.2006 17:54

Chat (Linked List) Frage

Beitrag von kiki »

Hallo,

Ich habe einen kleinen Chat geschrieben. Ich poste mal hier den Code, vielleicht habt ihr noch Ideen, was man daran noch verbessern kann. Manchmal klappt da nämlich was nicht.

Server:

Code: Alles auswählen

InitNetwork()
*Buffer = AllocateMemory(1000)
CreateNetworkServer(1, 6705, #PB_Network_TCP)

Structure UserDaten
Nickname.s
EndStructure 

Structure UserName
Nickname.s
EndStructure 

Structure UserID
ID.l
EndStructure 

Global NewList UserName.UserName()
Global NewList UserID.UserID()

Global UserDaten.UserDaten
Global SEvent
Global ClientID 

Repeat
    SEvent = NetworkServerEvent()
    If SEvent
      ClientID = EventClient()
      Select SEvent
      
        Case 1
        
        AddElement(UserID())
        Debug "Connect"
        Debug ClientID
        UserID()\ID.l = ClientID
        
        Case 2
        
        FreeMemory(*Buffer)
        *Buffer = AllocateMemory(1000)
        
        ReceiveNetworkData(ClientID, *Buffer, 1000)
        Meldungstext$ = PeekS(*Buffer)
        TextInhalt$ = Mid(Meldungstext$, 10, Len(Meldungstext$)-9 )
        Meldung$ = PeekS(*Buffer, 8, 0)
        
        
        If Meldung$ = "Nickname"
        AddElement(UserName())
        UserName()\Nickname.s = TextInhalt$  
        ForEach UserID()
        SendNetworkString(UserID()\ID.l, "Clearing:test")
        Delay(500)
        ForEach UserName()
        Weiter = 0
        SendNetworkString(UserID()\ID.l, "UserUser:"+UserName()\Nickname)
        Delay(500)
        Next
        Next 
        EndIf 
        
        
        If Meldung$ = "Nachrich"
        ForEach UserID()
        SendNetworkString(UserID()\ID.l, "Nachrich:"+TextInhalt$)
        Next 
        EndIf 
        
        If Meldung$ = "ExitExit"
        Ende = ClientID
        EndIf 
        
        Case 4   
        
        ForEach UserID() 
        NextElement(UserName())
        If UserID()\ID = ClientID
        DeleteElement(UserID())
        DeleteElement(UserName())
        EndIf 
        Next
        
         ForEach UserID()
        SendNetworkString(UserID()\ID.l, "Clearing:test")
        Delay(500)
        ForEach UserName()
        Weiter = 0
        SendNetworkString(UserID()\ID.l, "UserUser:"+UserName()\Nickname)
        Delay(500)
        Next
        Next 

        
          EndSelect
    EndIf
    
  Until Quit = 1 


Client:

Code: Alles auswählen

Global Nickname$

Structure ServerDaten
User.s
EndStructure 

Global ServerDaten.ServerDaten
Global ConnectionID

Down = 0
*Buffer = AllocateMemory(1000)

Procedure Haupt(dumma.l)
If OpenWindow(1, 283, 26, 480, 418, Nickname$,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
      EditorGadget(10, 10, 10, 280, 350)
      EditorGadget(11, 320, 10, 140, 350)
      StringGadget(12, 10, 380, 300, 20, "", 0)
      EndIf 
       Repeat
       
       If GetAsyncKeyState_(#VK_RETURN)
        Repeat 
        Until GetAsyncKeyState_(#VK_RETURN) = 0
         NachrText$ = GetGadgetText(12)
         SendNetworkString(ConnectionID, "Nachrich:"+NachrText$)
         SetGadgetText(12, "")
       EndIf 
       
        EventID = WaitWindowEvent(1)
       Until EventID = #PB_Event_CloseWindow
       SendNetworkString(ConnectionID, "ExitExit")
       Delay(500)
       Down = 1
EndProcedure 


Procedure Nickname(dummb.l)
  If OpenWindow(0, 383, 268, 292, 97, "New window ( 0 )",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
      StringGadget(1, 10, 30, 280, 23, "")
      TextGadget(2, 10, 10, 85, 18, "Dein Nickname:")
      ButtonGadget(3, 110, 60, 70, 25, "OK", #PB_Button_Default | #PB_Button_Toggle)
  EndIf
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_Gadget
      Select EventGadget()  
        Case 3
        Nickname$ = GetGadgetText(1)
        CloseWindow(0)
        Break 1
         EndSelect 
    EndIf 
  Until EventID = #PB_Event_CloseWindow
  EndProcedure 
  
Procedure Connect(dummc.l)

;- Init
Down = 0
*Buffer = AllocateMemory(1000)
InitNetwork()

Repeat 
ConnectionID = OpenNetworkConnection("127.0.0.1", 6705)
Until ConnectionID <> 0
SendNetworkString(ConnectionID, "Nickname:"+Nickname$)

Repeat 
Delay(300)
  ServerID = NetworkClientEvent(ConnectionID) 
    Select ServerID
 
      Case 2 
        Meldungstext$ = ""
        Meldung$ = ""
        TextInhalt$ = ""
        FreeMemory(*Buffer)
        *Buffer = AllocateMemory(1000)
  
        ReceiveNetworkData(ConnectionID, *Buffer, 1000)
        Meldungstext$ = PeekS(*Buffer)
        TextInhalt$ = Mid(Meldungstext$, 10, Len(Meldungstext$)-9 )
        Meldung$ = PeekS(*Buffer, 8, 0)
        
        
          If Meldung$ = "UserUser"
          ServerDaten\User.s = TextInhalt$
          AddGadgetItem(11, 0, ServerDaten\User.s, 0, 0)
          EndIf 
        
          If Meldung$ = "Clearing"
          ClearGadgetItems(11)
          EndIf 
        
          If Meldung$ = "Nachrich"
          AddGadgetItem(10, 0, TextInhalt$, 0, 0)
          EndIf 
          
          If Down = 1
          CloseNetworkConnection(ConnectionID)
          Delay(1000) 
          End 
          EndIf 
        
    EndSelect 
  
 Until Quit = 1
  
EndProcedure

Nickname(dummb.l)

CreateThread(@Connect(), 99)

Haupt(dumma.l)

Zuletzt geändert von kiki am 02.02.2009 19:11, insgesamt 1-mal geändert.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Chat

Beitrag von Kiffi »

kiki hat geschrieben:Manchmal klappt da nämlich was nicht.
Was klappt da manchmal nicht?
kiki hat geschrieben:vielleicht habt ihr noch Ideen, was man daran noch verbessern kann
den Code vernünftig einzurücken wäre doch schon mal ein guter Anfang.

Grüße ... Kiffi
a²+b²=mc²
kiki
Beiträge: 155
Registriert: 06.05.2006 17:54

Beitrag von kiki »

Ist schwierig zu Erklären. Aber ich versuchs mal. Also ich Füge zu dem Server "Client 1" hinzu. Dann füge ich auch "Client 2" hinzu. Wenn ich nun die Verbindung von "Client 2" unterbreche. Steht in der Liste, es gibt nur noch "Client 1". <<< Das ist richtig. Wenn aber aber stattdessen "Client 1" trenne. Steht da, immer noch, das Client 1 online wäre und Client 2 nicht.

Ich habe warscheinlich etwas an den LinkedLists Falsch gemacht.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

also, was schon mal grundsätzlich falsch ist, ist dieses:

Code: Alles auswählen

Structure UserName
Nickname.s
EndStructure

Structure UserID
ID.l
EndStructure

Global NewList UserName.UserName()
Global NewList UserID.UserID() 
zwei listen für Name und ID?
dadurch stehen die in keinerlei Beziehung zueinander, das kann doch nicht Sinn der Sache sein.
da schwebte dir wohl eher sowas vor:

Code: Alles auswählen

Structure UserInfo
  ID.l
  IP_Add.l
  Nickname.s
EndStructure
... und was das sinnvolle Einrücken betrifft, da könntest du wirklich ein bissel fleißiger sein.

ich finde jetzt auf die schnelle nicht die stelle, wo es "Client1" und "Client2" benamst...
kiki
Beiträge: 155
Registriert: 06.05.2006 17:54

Beitrag von kiki »

Also wenn sich ein neuer Client mit dem Server verbindet, wird folgendes gemacht:

Alte Version:

Code: Alles auswählen

 AddElement(UserID())
        UserID()\ID.l = ClientID
Neue Version:

Code: Alles auswählen

 AddElement(UserInfo())
        UserInfo()\ID.l = ClientID
Das müsste soweit richtig sein.

Als nächstes sendet der Client dem Server seinen Nicknamen. Der gesendete String sieht dass so aus: "Nickname:Manfred"

Jetzt wird die Funktion Nickname ausgeführt:

Alt:

Code: Alles auswählen

AddElement(UserName())
        UserName()\Nickname.s = TextInhalt$  
        ForEach UserID()
        ForEach UserName()
        Weiter = 0
        SendNetworkString(UserID()\ID.l, "UserUser:"+UserName()\Nickname)
        Delay(500)
        Next
        Next 

Neu:

Code: Alles auswählen

       UserInfo()\Nickname.s = TextInhalt$  
Als nächstes wird jeder Nickname an jeden Client gesendet

Code: Alles auswählen

        ForEach UserInfo()
        ForEach UserInfo()
        SendNetworkString(UserInfo()\ID.l, "UserUser:"+UserInfo()\Nickname)
        Delay(500)
        Next
        Next 
Und der Code kann ja nicht klappen, daswegen habe ich 2 Listen gemacht.

Wie soll ich es sonst schaffen, dass alle Nicknamen nacheinander an alle Clients gesendet werden.[/code]
Benutzeravatar
HeX0R
Beiträge: 3042
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

So:

Code: Alles auswählen

ForEach UserInfo()
	*Index = @UserInfo()
	ID     = UserInfo()\ID
	ForEach UserInfo()
		If UserInfo()\ID <> ID
			SendNetworkString(ID, "UserUser:" + UserInfo()\Nickname)
		EndIf
	Next
	ChangeCurrentElement(UserInfo(), *Index)
Next
Aber besser wäre es, das zu bündeln, sonst produzierst du nen Ar... Sack voll Daten.
Also eine Liste der Nicks am Stück senden (darauf achten, dass das Trennzeichen im Nick nicht vorkommen darf).
So in etwa:

Code: Alles auswählen

Names.s = ""
ForEach UserInfo()
	Names + UserInfo()\Nickname + ";"
Next

ForEach UserInfo()
	SendNetworkString(UserInfo()\ID, "User:" + Names)
Next
Antworten