Osaisiko joku kertoa minulle, miten voin tehä winsock:n avulla online listan? Eli kaikkien käyttäjien nick:it näkyvät reunassa tree viwerissä. Esim:
Käyttäjät |---------------| |ismo | |sikke | |ukko | |tepi^ | |---------------|
Eli siis olen tekemässä chattiä...
Jos ei tuollainen onnistu, niin miten sitten koko chatti? :)
Periaatteessahan tuo onnistuis jotenki sillä tavalla, että kun serveriin yhdistää, niin serveri lähettää sitten kaikille muille viestin, että kyseinen henkilö tuli. Sitten clientit vaan lisäävät henkilön listaan. Mikä tässä on epäselvää? Kysymyksestäsi ei käy se ilmi.
Ja tietenkin sitten sille kirjautujalle lähetetään kaikki nimet.
Aina kun servulle joinitaan, servu pyytää käyttäjältä nickiä esim /annanicki, sitten client kun huomaa, että tämmönen viesti on tullut, se lähettää takaisin /munnicki|nicki_tähän.
Servu on sitten että "ahaa! onpas komia!" ja lähettää sen kaikille muille, jotka on yhdistyneenä ja lisää nickin johonkin muuttujaan, jossa on muiden nickit myös. Nickit = nickit & uusi_nicki & "|" (toki tähän varmaan kannattaa käyttää jotain taulua).
Tämän jälkeen serveri lähettää tälle, joka juuri yhdisti namelistin. Esim "/namelisti:" & nickit
ja client sitten parsii ton ns. oikeanlaiseksi.
Split on tässä varsin kätevä, siihen kannattaa tutustua, jos pääsee parsii tietoa.
Miten sitten pystyn poistamaan listasta juurin sen oikean nick:in? Eli pystyykö jollain tyylillä esim nyt laskemaan mikä on nickin: sepi lista id?
No säilytät niitä taulukossa.
Sepin id on taulukon indeksi, jossa sepi on.
Siis jos nickit(1) = "simo" ja nickit(2) = "sepi" ja nickit(3) = "ismo", niin sepin id on 2.
Itse ainakin säilytän noita clientti-socketteja taulukossa, ja ne menevät ihan vastaavassa järjestyksessä.
Siis esim. jos socketista, jonka id on 1 lähettää joku viestin, tiedämme että se on simo. (viitaten äskeiseen esimerkkiini)
Tuo on ainakin nopeampi idea kuin että käydään taulukko läpi.
No poistokomentohan voisi olla vaikka
POISTA <clientin id>
Toki kaikilla pitää olla nickit samassa järjestyksessä, joten ne pitää lähettää oikeassa järjestyksessä clientille.
Kun clientti lähtee, socketit huomaa että sieltä on disconnectattu (socketista jonka id on 3) ja nyt serveri tietää että ismo on lähtenyt.
Sitten se lähettää muille clienteille "POISTA 3".
Näin siis voit tehdä, mutta toki on muitakin tapoja.
Jep mutta piti vielä ksysyä, että eikö 1 socketista voi lähettää enempää dataa kuin 1? siis esim nyt soketti1 josta mene kaikki viesti teksti eli minkä käyttäjä tai serveri on kirjoittanut.niin eikö siinä samssa socketissa voisi mennä vaikka juuri tämä käyttäjä lista? Meinaa jos se menee, niin se printataan ihan samalla tavalla tuohon viesti ruutuun ja se taas ei olisi hyvä
Tietenkin ne menevät samasta socketista.
Sinun pitää parsia.
Eli esimerkkiä peliin:
Serveri lähettää viestin "VIESTI Sepi Moi olen paikalla".
Clientti katsoo että jahas, eka sana on "VIESTI", lähettäjä on Sepi ja itse viesti on "Moi olen paikalla".
Koska tämä on viesti, clientti tulostaa sen viestiruutuun ja laittaa Sepin lähettäjäksi.
Ja kun taas clientti yhdistää serveriin, niin serveri lähettää viestin "KAYTLIST Simo Sepi Ismo".
Sitten clientti huomaa, että jahas serveri kertoo käyttäjälistan.
Ensimmäinen käyttäja on Simo, toinen Sepi ja kolmas Ismo.
Nuo olivat vain siis esimerkkikomentoja, voisihan KAYTLIST olla annakayttajalista.
Kaikki riippuu sinusta.
Ja komentolistaa pitää tietenkin laajentaa oman käyttötarkoituksen mukaan.
Jos sulla on käyttäjät vaikka Listboxissa niin siihen voi tehdä hyvin yksinkertaisen funktion.
Public Function PoistaNickListasta(LB As ListBox, Nick As String) Dim I As Long For I = 0 To LB.ListCount - 1 If LB.List(I) = Nick Then LB.RemoveItem (I) Next I End Function 'käyttö esim Sub Form_Load() PoistaNickListasta List1, "tesmu" End Sub
Ja jos haluat että kirjainkoolla ei ole väliä niin.
muuta
If LB.List(I) = Nick Then LB.RemoveItem (I)'seuraavanlaiseksi If UCase(LB.List(I)) = UCase(Nick) Then LB.RemoveItem (I)
Tietysti tuo voi olla LCase myös (UCase = Upercase = Isot kirjaimet) (LCase = Lowercase = Pienet kirjaimet)
Toimiiko tuo samalla tavalla tree viwessä?
Edit1: Toimiiko splittaus näin?
Dim data As String Dim muuntaja As Variant soketti(0).GetData data muuntaja = Split("data", "|") Select Case muuntaja(0) Case "/viesti" tekstit.AddItem "<" & muuntaja(1) & "> " & muuntaja(2) End Select
muuntaja = Split([b]data[/b], "|")
Näin että se splittaa data, ei merkkijonoa "data", jossa on merkit d, a, t, a.
Ja näyttäisi siltä, että viesti lähetätään sinun protokollassasi näin:
/viesti|Sepi|Moi olen paikalla
jep huomasin sen itsekkin... :D...
Nyten taas olisi sellanen probleema että sen saa millään yhdsitettyä serveriin enemmän kuin yhden clientin...Eikös sen pitäisi tän avulla pystyä yhdistämään enemmänkin?
soketti(Index).Close DoEvents soketti(Index).Accept requestID Load soketti(soketti.Count) soketti(soketti.UBound).LocalPort = 3210 soketti(soketti.UBound).Listen
Miten voin lähettää dataa kaikkiin socketteihin yhtä aikaa? Eli ettei se lähetä sitä vain yhdelle socketille.
'Tämähän lähettää dataa vain sille index:lle mistä data on tullut vai mitä? soketti(Index).SendData (data)
Eli minun pitäisi saada selville kaikki yhteydessä olveline sockettejen indexi, eli miten saan sen selville?
Jos tuohon laittaa
sokettimaara = soketti.cout for i = 0 to sokettimaara soketti(i).SendData (data) doevents next
tuohon aloittaa laskunsa ykkösestä eikö? Eli sekään ei toimi tässä... Eli miten saan selville sokettit nollasta lähtien???
Vähennä määrästä yksi.
1 To Maara
0 To Maara - 1
Vai mitä tarkoitat? Kysymyksistäsi ei ota örkkikään selvää.
kokeilin mutta ei toimi... Eli siis serverin pitäisi saada lähetettyä kaikille clienteille sama viesti...
Sama viesti kaikille:
For i = 0 To socketti.Count - 1 'käydään ladattujen sockettien määrän verran kierroksia If socketti(i).State = sckConnected Then 'jos on socketti yhdistyneenä DoEvents socketti(i).SendData "lähetetään tää viesti kaikille" 'silloin sille voi lähettää dataa, ellei ole mennyt ihan kunnolla hölmöilemään muualla. DoEvents End If Next i
....kiitos paljon...
Nytten lupaan että tämä on viponen kerta kun kysyn apua tästä chatistä... Eli mikä tuossa käyttäjä taulukossa on vikana? Eli tuon olisi tarkoitus etttä lähetetään käyttäjä taulukko yhditäneelle uudelle käyttäjälle ja tämän jälkeen hänen nick tunnus lisätän kayttajat taulukkoon.
Dim kayttajat(0 to soketti.cout - 1) as string Dim i as integer 'muuntaja(1) sisältää nick:in for i = 0 to soketti.count - 1 'Lähetetään käyttäjä taulukko juuri yhdistäneelle käyttäjälle soketti(Index).sendData("/kayttajat|" & kayttajat(i)) doevents next i 'Lisätään uusi nick:i käyttäjä listaan kayttajat(soketti.Count - 1) = muuntaja(1)
Suosittelen että muodostat ensin käyttäjistä merkkijonon, jota et tee näyttämässäsi koodissa. Nyt koodisi alustaa käyttäjät uudelleen (tuhoaa tiedot käyttäjistä), jonka jälkeen se yrittää lähettää jokaiseen sokettiin eri tietoja. Muodosta ensin yksi merkkijono, jossa on käyttäjien tiedot oikein laitettuna, ja vasta sitten yritä lähettää sitä. Tarkoitan tällä että kirjoittaisit lähetettävät tiedot vaikka johonkin textbox:iin, niin voit korjata tämän koodin ennen kuin yrität edes lähettää tätä virheellistä tietoa.
Korjauksia:
Dim kayttajat(0 to soketti.cout - 1) as string 'Miksi tämä on tässä ? eikö tämä pitäisi alustaa paljon aikaisemmin
Tee ohjelmaasi funktio Lähetä_kaikille(viesti as string), joka hoitaa viestin lähettämisen kaikille. Tällöin voit keskittyä paremmin tuohon käyttäjien nimien kopioimisen yhteen merkkijonoon.
hmm,olisitko niin kiltti, että väsäisit minulle sen funktion. Itselläni ei ole oikein mitään hajua miten tämän funktion tulisi toimia. Muutenkin funktioitten teko on huonoin puoli siitä mitä nyt satun osaamaan
Edit1:
Tuohan on tyhmä idea, että minä itse kirjoitaisin komennon textibox:iin.. Minähän joutuisin lähettää yhteydessä oleville käyttäjien nick:it kokoajan uusille clienteille ja siinbä ei olisi mitään järkeä....
Mahdatko nytten tietämään mitä tarkoitan ja mitä olen tekemässä? Eli olen tekemässä chattiin käyttäjä listaa jossa näkyy kaikkien yhteydessä olevien käyttäjien nick:it
Tarkoitin että tee ensin se koodi, joka muodostaa käyttäjistä sen merkkojonon ja varmista että se menee oikein ennen kuin edes lisäät lähettämiseen tarvittavan koodin. Tämä sen takia koska antamassasi koodissa ei ole mielestäni järkeä. Mielestäni yleensä on parempi asia tehdä asiat pienissä erissä, ja varmistaa välillä että ne toimivat. Koodissasi on vaikutelma että kaikki on kasattu nopeasti kasaan ymmärtämättä mitä tekee.
Mielestäni on kannattavaa pätkiä koodia funktioihin, koska siten hankalasta koodista saa selkeämpää. Myös asiat joita tullaan tekemään useasti kannattaa tehdä funktioihin tai sub:eihin. Uskon että tulet tarvitsemaan kaikille asiakkaille lähettämistä monessa asiassa (vaikka asiakkaan potkiminen), ja tällöin sinun ei tarvitse kirjoittaa samaa koodia monesti.
Sub Päivitä_käyttäjälista() dim i as integer dim käyttäjälista as string = "/kayttajat|" For i = 0 to Ubound(Käyttäjät) käyttäjälista = käyttäjälista & Käyttäjät(i) next i 'Nyt sinulla pitäisi olla merkkijonossa käyttäjälista lähetettävä tieto Esim. "/kayttajat|Erkki|Matti|Tuula" Lähetä_kaikille(käyttäjälista) 'Välitetään tämä merkkojono sub:ille joka huolehtii sen toimittamisesta kaikille End Sub Sub Lähetä_kaikille(Viesti as string) 'Tämän koodin jo tiedätkin End sub
Sori jos koodissa on jotain virheitä, mutta ei ole vb6:tosta tällä koneella niin en voi varmistaa tota. Ymmärrät kuitenkin varmaan pääperiaatteen miten ton pitäisi toimia.
Eli siis tuo on vain malli siihen...Eli siis minun pitäisi tehä tuohon ainakin vielä se Käyttäjät taulu missä kaikki käyttäjät ovat tauluissa vai?
Siis tarkoititko et tekisin näin...
Case "/liityn" kaytajo.AddItem muuntaja(1) kayttajalistaam(soketti.UBound) = muuntaja(1) MsgBox kayttajalistaam(soketti.UBound) Lähetä_kaikille (käyttäjälista) End Select End Sub Sub Päivitä_käyttäjälista() Dim i As Integer Dim käyttäjälista As String käyttäjälista = "/kayttajat|" For i = 0 To UBound(kayttajalistaam) käyttäjälista = käyttäjälista & kayttajalistaam(i) MsgBox kayttajalistaam(i) Next i End Sub Sub Lähetä_kaikille(käyttäjälista) Dim käyttäjälista As String Dim aw As Integer For aw = 0 To soketti.Count - 1 If soketti(aw).State = sckConnected Then soketti(aw).SendData käyttäjälista DoEvents End If Next aw End Sub
tässä koko juttu...
Tarkoitin että varmistat ensin että koodisi muodostaa oikean mallisia viestejä käyttäjille, jotta ne osaavat käsitellä sen oikein. Tämä onnistuu helpoiten käyttämällä msgboxeja. Kun olet varmistanut että funktio tai subi toimii oikein niin ne msgboxit kannattaa poistaa, koska ne ovat sen jälkeen turhia.
Mielestäni käyttäjien nimet tulisi säilyttää taulukossa, jolloin niitä on nopeampi ja helpompi käyttää. Olen ymmärtänyt että ongelma on saada muille keskustelijoille toistensa nimet. Serverin on helppo saada tietää kaikkien nimet, ja serverin kuuluu lähettää nämä tiedot kaikille. Miten muuten henkilöt voivat tietää ketä on samalla servulla.
Ymmärrätkö mitä koodisi tekee? En usko että valmista koodia antamalla ymmärtäisit miten tässä pitäisi mielestäni toimia. Jos sinulla on hankaluuksia funktioiden ja muiden tärkeiden asioiden hallinnassa suosittelen että lukusit Ohjelmointiputkan vb oppaat vielä kerran ajatuksella läpi.
Tarkentaisitko vielä että missä ongelma on tarkalleen, koska käyttäjälistan tekeminen ei onnistu ihan helposti, enkä haluaisi antaa suoraan koodia kaikkeen.
Korjaus:
Sub Lähetä_kaikille(käyttäjälista) 'määrittele käyttäjälista n tyyppi (esim "käyttäjälista as string") Dim käyttäjälista As String ' Tämä koodi alustaa(tyhjentää) juuri saamasi käyttäjien nimet (tämä pitäisi poistaa)
onko koodi muuten oikein?
Sehän riippuu aivan mitä yrität saavuttaa. Toimiiko ohjelma niin kuin sen on tarkoitus? Jos toimii, niin koodi on oikein, mutta jos se ei toimi niin koodi ei ole oikein. Jos et yritä enää etsiä sieltä virheitä, niin ainakin poista nuo msgboxit.
https://www.ohjelmointiputka.net/koodivinkit/
tuollainen tuli tossa nopeasti väsättyä ja voit siitä katsoa mallia. Jos et ymmärrä jotain, niin lue ensin kommentit ja sitten katso jos löytyy oppaasta apua. Jos sieltäkään ei löydy apua niin jatka kyselemistä. Ei kukaan osaa kaikkea syntyessään.
nomic kirjoitti:
Sama viesti kaikille:
For i = 0 To socketti.Count - 1 'käydään ladattujen sockettien määrän verran kierroksia If socketti(i).State = sckConnected Then 'jos on socketti yhdistyneenä DoEvents socketti(i).SendData "lähetetään tää viesti kaikille" 'silloin sille voi lähettää dataa, ellei ole mennyt ihan kunnolla hölmöilemään muualla. DoEvents End If Next i
Tuota DoEventsiä ei joka riville tarvii laittaa... tuo jälkimmäinen riittää...
Pöytälamppu kirjoitti:
https://www.ohjelmointiputka.net/koodivinkit/
24511-vb6-yksinkertainen-käyttäjälista
Kiitos paljon Pöytälamppu tästä sinun vaivan näöstäsi....Jos vain haluat voin laittaa ohjelmaan merkinnän avustasi....
Edit1: Miksi minulla tulee virhe ilmoitus? Eli siis tuossa
Function Listaa_käyttäjät(Optional Erotin As String = vbCrLf) As String Dim i As Integer Dim retuni As String 'käydään kaikki käyttäjät läpi For i = 0 To UBound(Käyttäjät) 'TÄSSÄ TULEE VIRHE ILMOITUS! If i = 0 Then 'ensinmäinen lisätään returniin ilman erotinta retuni = Käyttäjät(i).name Else 'muut lisätään returniin erottimen kanssa retuni = retuni & Erotin & Käyttäjät(i).name End If Next Listaa_käyttäjät = retuni End Function
Eli siis se valittaa "Subscript out of range" mikä vikana?
tesmu kirjoitti:
Tuota DoEventsiä ei joka riville tarvii laittaa... tuo jälkimmäinen riittää...
Totta. Olen vain vainoharhainen ja jäänyt huonoksi tavaksi pistellä tuota vähän joka kohtaan. ;)
Juu tuohon unohtui muutama virhe nopeasti kun tein. Päivitin koodivinkin, nyt pitäisi toimia.
Olisiko mitenkään mahdollista laskea nimien määrän?
eli siis "/liityn|mikko|esko|saku|sanna" tuon /liityn jälkeen niin pitäisis saada selville, että siinä on 4 nimeä.
No sen jälkeen, kun tieto on splitattu, laskeminen ei ole vaikeaa.
nimilista = "/nimet|1|2|3" 'se missä on kaikki nimet splitattu = Split(nimilista, "|") 'splitataan roska MsgBox "nimilistasta löytyi " & UBound(splitattu) & " nimeä." 'kerrotaan vähän ja käytetään uboundia
ok no nyt voisisin kysyä mitä tuo UBound tekee?
Edit1:
Eikös tuon pitäisi lähettää käyttäjä taulukko uudelle clientille?
soketti(Index).SendData (Listaa_käyttäjät("|"))
Onko tämä koodi ylipäätänsä oikein meinaa clientti joka käyttää sokettia 0 toimii täysin oikein ja siitä ylös päin ne ei saa ollenkaan käyttäjälistaa
Case "/liityn" kaytajo.AddItem muuntaja(1) soketti(Index).SendData (Listaa_käyttäjät("|")) Lisää_käyttäjä (muuntaja(1)) For sw = 0 To soketti.Count - 1 If soketti(sw).State = sckConnected Then soketti(sw).SendData ("/liityn|" & muuntaja(1)) DoEvents End If Next sw End Select
Minkä hiton takia nimien väliin tulee aina "
" sellaiset ihme merkit jotka ei nyt ilmeisemmin näy tässä näin...
Edit eli siihen tulee aina kaksi ihme merkkiä ja se sekottaa järjestelmän... Eli nämä merkit taitavat kuvata rivin vaihtoa jos oikein ymmärsin...
Vika korjattu muutin kohdan
retuni = retuni & Erotin & Käyttäjät(i).name
Muotoon
retuni = retuni & "|" & Käyttäjät(i).name
Ahahah, Clienttien käyttäjälistat vi***ilee vieläkin...
Tässä clienttin vastaan otto koodi
Case "/liityn" niim = UBound(muuntaja) For py = 1 To niim kayttajalista.AddItem muuntaja(py) DoEvents Next py
Uboundin selitys löytyi haulla:
https://www.ohjelmointiputka.net/keskustelu/
Jos serverille tulee uusi käyttäjä, pitää serverin välittää tästä tieto kaikille asiakkaille. Tämä onnistuu joko kertomalla asiakkaille ketä tuli mukaan tai lähettämällä kaikkien käyttäjien nimet asiakkaille uudestaan.
Niinhän minä olen tossa tehnytkin
Case "/liityn" kaytajo.AddItem muuntaja(1) 'lisätään uusi käyttäjä serverille soketti(Index).SendData (Listaa_käyttäjät("|")) 'Lähetetään käyttäjä lista uudelle asiakkaalle Lisää_käyttäjä (muuntaja(1)) 'Lisätään uusi asiakas käyttäjälistaan For sw = 0 To soketti.Count - 1 'Tämän avulla käydään läpi kaikki asiakkaat If soketti(sw).State = sckConnected Then 'jos ollaan yhteydessä soketti(sw).SendData ("/liityn|" & muuntaja(1)) 'lähetetään kaikille uuden asiakkaan nick:i DoEvents End If Next sw End Select
Kaikessa yksinkertasuudessaan haetaan listboksista kaikki käyttäjien nimet sitten lähetetään ne käyttäjälle tällätavalla "NIMET ekanimi tokanimi kolmas" & vbcrlf
Sitten kun haetaan dataa winsockilla niin näin
Sub socketti_DataArrival(Index as integer) 'muuta tuo subi oikeaksi Dim Datat As String Dim Params() As String Dim I as Long socketti(index).GetData Datat Params = Split(Datat," ") Select Case UCase(Params(0)) Case "NIMET" For I = 1 To UBound(Params) nimilista.AddItem Params(I) Next I End Select End Sub
Tämä on vähän sama kuin irc protokollassa joinattaessa kanavalle serveri lähettää nimilistan... Toki nimilistan saat haettua myös NAMES #kanava komennolla
tosin irc protokollassa nimet lähetetään näin
:servunosotetainimi 353 sunnick = nimi1 nimi2 nimi3 nimi4 jne
Mutta kaikista helpommin tuo menisi tuollatavalla
Eikös tuo ole clientiin tuleva vastaanotto koodi?
kayttaja-3842 kirjoitti:
Eikös tuo ole clientiin tuleva vastaanotto koodi?
kyllä
ja kun clientti yhdistää se toimittaa servulle nimimerkin ja servu varastoi sen ja ainaku uus clientti yhdistää se varastoi sen lähettämän nickin ja lähettää nimilistan uudelle clientille sekä ilmotuksen uudesta käyttäjästä kaikille muille
ahaaa...Kitos paljon nytten se toimii täysin ilman mitään bugeja...:D Kädestä pitäen se mulle piti näyttää, mutta onnistuinpa kummiskin :D...Kiitos paljon vielä kerran :D
Ootte parhaita.....
Aihe on jo aika vanha, joten et voi enää vastata siihen.