Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

[TuT] TCP w AutoIt na przykładzie czatu i minigry


hfaua

Rekomendowane odpowiedzi

Opublikowano

Witajcie,

Jako iż pewny użytkownik napisał do mnie z prośbą o tutka o TCP, postanowiłem takowego napisać. Najpierw opiszę wszystkie funkcję, napiszę do czego służą, napiszę który argument za co odpowiadam potem, przedstawię jakiś tam przykład servera i clienta, a na końcu "grę", która miała polegać na chodzeniu i strzelaniu, ale z braku czasu <Borderlands 2> wyszło tylko chodzenie. Sorry, może jak będzie mi się kiedyś chciało, albo mnie ktoś będzie nękał na PW to dokończę ;] Od razu ostrzegam, że gra była pisana przez jedno popołudnie i polega tak na prawdę na przemieszczaniu Label'ów :D

 

A więc, życzę miłej lektury :)

 

No to ten...

1. Wstęp

TCP - no to jest to protokół służący do komunikacji sieciowej klient-server. Mamy server, do niego podłączają się klienci, przesyłają mu informacje, on je przetwarza i wysyła do pozostałych jeśli zachodzi taka potrzeba. Coś nie jasne? To piszcie w komentarzach, to potem edita dam ;]

 

2. Funkcje

A więc tak. Przydało by się to ustrojstwo włączyć ;] TCPStartup(). Myk, włączone. Tyle. Koniec, nie trzeba się pierdolić w różnego rodzaju pierdolenie się z jakimiś ustawieniami czy czymś. Potem jak już kończymy działanie naszego programu wypadałoby posprzątać po sobie, czyli TCPShutdown(). Oczywiście, tak jak idąc ulicą nie musimy wyrzucać puszki po piwie do kosza, bo jakiś gościu podniesie i będzie miał na złom i kupi sobie Amarenkę <3, tak nie musimy tego używać, jeśli komunikacja kończy się w momencie wyłączenia programu, ktoś po prostu to zrobi za nas.

 

Dobrze, mamy włączoną usługę TCP. Super. Teraz może by tak coś ambitniejszego? Bo na co nam włączone TCP, jak nie mamy się z czym połączyć, nie? No to dajemy. Serwer. Do niego będą podłączone nasze klienty <podłączeni nasi klienci?>. Na początku zróbmy sobie prostą tablicę $client[10], bo nie chcemy żeby się więcej niż 10 gości podłączało jednocześnie ;] Tam będziemy trzymali sockety. Ale co to socket?

 

Socket - to nasze gniazdo w połączeniu. Pozwala nam się komunikować z serwerem <klientem>. Serwer tworzy sobie taki główny socket którym będzie nasłuchiwał czy jakieś klienty się połączyć z nim nie chcą, albo nie przysyłają mu jakiś danych. Przykładzik. Mamy czat. Użytkownik A pisze "Siema", wysyła się to do serwera, serwerowi to na nic nie jest potrzebne, ale czat polega mniej więcej na tym, żeby dwie, lub więcej osób mogło sobie porozmawiać, więc serwer wysyła do osób B i C tą informację którą wysłała osoba A. Klient osób B i C to sobie przetwarza i voila! Mamy wiadomość u pozostałych rozmówców. Tak, to właśnie gniazda przesłały te informacje. Nasz serwer ma w naszej tablicy $client[10] gniazda do klientów. Z tym, że w AutoIt są to po prostu ich identyfikatory. Ale to taka mało istotna informacja. Teraz przelatuje sobie po tablicy od góry do dołu, od dołu do góry, czy jak tam sobie chce i wysyła do wszystkich informację że osoba A napisała "Siema". Oczywiście do niej samej nie ma sensu tego wysyłać, więc ją pomijamy.

 

W serwerze aby stworzyć główny, nasłuchujący socket używamy funkcji TCPListen. Przyjmuje ona trzy argumenty i zwraca identyfikator do socketa nasłuchującego. Adres IPv4, port oraz maksymalną długość kolejki połączeń oczekujących. Możemy go ustawić na dowolny adres, więc czemu by nie localhost. No to wpisujemy "127.0.0.1" <adresy ip będziemy zapisywali w postaci stringa>. Dobrze, teraz port. W zasadzie możemy użyć prawie każdego portu. Porty mamy w zakresie 0 - 65535, czyli 2^16 możliwych portów :) całkiem dużo możliwości. Niektóre są zarezerwowane, ale jest też duuuużo dużo wolnych. My sobie weźmiemy porcik 1337. Z tego co sprawdzałem to nie jest zajęty przez żadna usługę, więc śmiało możemy z niego korzystać :) Dobrze, teraz długość kolejki. Dajmy sobie 10, nie ma sensu więcej, bo mamy max 10 klientów. Oczywiście identyfikator nasłuchujący zapisujemy sobie do jakiejś zmiennej, dajmy na to $Socket, żeby oryginalnie było.

 

Ok. Nasz przyszły serwer już nasłuchuje połączeń, ale teraz musimy jakoś sprawdzać czy ktoś się faktycznie połączył z nami. Do tego służy funkcja TCPAccept, przyjmująca jako argument nasz socket nasłuchujący. Super, my go już mamy od wywołania funkcji TCPListen. Więc dajemy TCPAccept($Socket). No tak, tylko, że tak funkcja zwraca identyfikator socketa naszego klienta. Ok. Jakby nie patrzeć to nam to na rękę, robimy sobie zmienną trzymającą w sobie ilość już połączonych klientów, będziemy jej używali do określenia miejsca w tablicy do którego zapiszemy identyfikator połączonego socketa. Zapomniałem wspomnieć, że TCPAccept będzie działało w głównej pętelce naszego serwera, ale penie Ci bystrzejsi się domyślili. Na razie nie uwzględniamy możliwości, że nasz klient się rozłączy, a na jego miejsce wejdzie inny <w tej grze na końcu jest to rozwiązane>. Może napiszę już jakiś kodzik przykładowego serwera, żeby wszystko jasne było :)

 

$l = 0;nasza zmienna informująca nas ile klientów jest połączonych z serwerem
$max_clients = 10;maksymalna ilość połączonych klientów
Dim $client[$max_clients]

TCPStartup()
$Socket = TCPListen("127.0.0.1", 1337, $max_clients)
If $Socket <= 0 Then; sprawdzamy czy się udało stworzyć naszego socketa głównego
MsgBox(16, "Server", "Tworzenie socketa nasłuchującego się zjebało...")
TCPShutdown()
Exit
EndIf

While True
If $max_clients > $l Then;jesli jest jeszcze miejsce do połączenia się
$sock = TCPAccept($Socket);sprawdzamy czy ktoś się chce z nami łączyć
If $sock > -1 Then; jeśli tak
MsgBox(64, "Server", "Nawiązałem połączenie z nowym klientem!", 2);stosowna wiadomość na 2sec
$client[$l] = $sock;dodajemy do tablicy nasze gniazdo
$l += 1;zwiekszamy nasz licznik o 1
EndIf
EndIf

for $i = 0 to $l
$bufor = TCPRecv($client[$i], 2048)
if $bufor <> "" Then
for $j = 0 to $l
if $j = $i then ContinueLoop
TCPSend($client[$j], $bufor)
Next
EndIf
Next
WEnd

 

 

Ok, myślę, że wszystko powinno być jasne :) Jeśli nie to piszcie, rozpiszę się bardziej <albo, co chyba lepsze, dokładniej...>. Dobra, przyjmujemy już połączenia od klientów. Ale jakich klientów?! Kto się połączy... oczywiście możemy sprawdzić czy nasz serwer działa. Wpisujemy w uruchom telnet, klikamy ENTER i wpisujemy "o localhost 1337", bez cudzysłowów ofc. Powinno się coś stać, albo wyskoczyć błąd, że jest zjebane. Kod piszę na żywca, więc może być coś nie teges, postaram się sprawdzić to przed opublikowaniem na MPC. Aha, no tak. Użytkownicy Win 7/Win Vista muszą sobie odblokować usługę telnet klient, bo ktoś uznał, że się nie przyda i wyłączył. Jak to zrobić znajdziecie bez problemów w google ;]

 

Teraz nie wiem, czy przejść do pisania klienta, czy może skończyć serwer, a klienta napisać na końcu. Chyba jednak bardziej zrozumiale będzie teraz klienta. Na końcu przedstawię oba kody, a teraz będę się starał pisać który kawałek kodu jest do którego programu.

 

3. Klient

Mamy serwer, czas na klienta <całą dzisiejszą noc mam wrażenie, że źle odmieniam to słowo...>. Dobrze, zastanówmy się co ma robić nasz klient? Teraz tak w trakcie pisania tego tutka zdecydowałem, że napiszemy sobie czat, więc klient ma następujące zadania do wykonania:

1)Włączyć usługę TCP

2)Połączyć się z serwerem

3a)Połączył się, idziemy dalej (4)

3b)Nie połączył się, kończymy zabawę z TCP i wyłączamy klienta. <Moglibyśmy bawić się w powtórne łączenie, ale po co? Nie chcą nas to trudno...>

4)Po wysłaniu wiadomości wysłać informację do serwera, że coś napisaliśmy

5)Dodać tą informację do listy wiadomości

6)Sprawdzić, czy serwer do nas nie wysłał informacji od innych użytkowników czatu

W sumie, parę punktów się uzbierało. Ok, przechodzimy do pisania.

 

Użyjemy paru nowych funkcji. Min.:

- TCPConnect(adres IP serwera, port serwera)

- TCPSend(socket odbiorcy, dane do wysłania)

- TCPRecv(socket nadawcy, maksymalna długość otrzymywanego ciągu danych, flagi)

 

Zacznijmy od omawiania pierwszej z nich. $Socket = TCPConnect("127.0.0.1", 1337). I tyle ;] W $Socket mamy socket serwera który teraz możemy używać do komunikacji z nim. Łączymy się z localhost'em, czyli z serwerem na naszym komputerze, chyba, że ktoś ma u siebie serwer to możemy wpisać jego IP z Hamachi np. Port którym się porozumiewamy to chyba jasne jest, ten sam co na serwerze. Myślę że wszystko jasne :) Funkcja zwraca nam identyfikator socketa z naszego serwera. Więcej się chyba nie da napisać o tym.

 

TCPSend. Chcemy wysłać informacje do serwera. Np. "Witaj serwerze! Jestem hax00rem i Cię zniszcze!!!11!1", co będzie dla niego niezbyt zrozumiałe, ale można postraszyć... Argumenty tej funkcji wymieniłem wyżej. Użycie? Send($Socket, "Hfaua na wysokości"). Wysyłamy co chcemy, albo string, albo dane binarne. Wysyłanie jak widzicie jest banalne.

 

TCPRecv. Teraz chcemy sprawdzić czy coś otrzymaliśmy od serwera. Np. Czy serwer nam odpowiedział "Witaj n00bku! Nie masz szans, jesteś cieńki, buehehehehehe!!!" Cwaniak. Argumenty mamy wyżej, więc przejdźmy od razu do użycia tej funkcji. Zwraca on nam dane otrzymane z gniazda podanego jako pierwszy argument <dane binarne lub string, zależnie od wartości ostatniego argumentu>.

 

Dobrze, więc teraz napiszmy naszego klienta.

 

TCPStartup()
$Socket = TCPConnect("127.0.0.1", 1337)
If $Socket <= 0 Then
MsgBox(16, "Klient", "Nieudane połączenie z serwerem!")
TCPShutdown()
Exit
EndIf

GUICreate("Klient", 250, 300)
$czat = GUICtrlCreateEdit("", 5, 5, 240, 230)
$input = GUICtrlCreateInput("", 5, 240, 240, 20)
$button = GUICtrlCreateButton("Wyślij!", 5, 265, 240, 30)
GUISetState()

While True
$msg = GUIGetMsg()
If $msg = -3 Then Exit
If $msg = $button Then
TCPSend($Socket, GUICtrlRead($input))
GUICtrlSetData($czat, GUICtrlRead($czat) & @CRLF & GUICtrlRead($input))
EndIf


$bufor = TCPRecv($Socket, 2048);dłuzszych wiadomości nie przewidujemy
If $bufor <> "" Then
GUICtrlSetData($czat, GUICtrlRead($czat) & @CRLF & $bufor);dobra dobra, to ma tylko działać, kto będzie chciał zrobi sobie lepsze...
EndIf
WEnd

 

 

Myślę że kod jest jasny. Łączymy się z serwerem, tworzymy GUI, jeśli klikamy button to się wysyła, sprawdza czy coś przyszło, jeśli tak to dodaje do Edit'a. Jeśli nie jasne coś jest to oczywiście komentarze i postaram się rozwinąć to ;] Oczywiście przepraszam za taki kod i za estetykę tego pr0 czatu. Tutorial nie pokazuje jak to najlepiej napisać <guictrlsetdata jest tragicznie zrobione, ale każdy kto umie zrobić lepiej zrobi sobie już sam>, tylko jak to zrobić, żeby działało, nie skupiam się na niepotrzebnych includach, funkcjach itd. To nie kurs AutoIt, tylko samego TCP. Myślę, że funkcję zostały jakoś tam w miarę opisane, korzystać już będziecie z tego umieli, a ja się przyczynię do rozwoju tego działu, bo takie założenia były. Tak BTW, bo mi się nie chce kolejnego posta pisać nigdzie, ta idea odrodzenia działów jeszcze żyje, czy nikomu się dalej nic nie chce? ;]

 

4. Jeszcze tak na szybko pozostałe funkcje TCP:

- TCPCloseSocket(socket) -> zamyka połączenie z socketem

- TCPNameToIP(string name) -> zamienia nazwę adresu na adres IP (np. google.com, mpcforum.pl itp.)

- TCPShutdown() -> pisałem już, wyłącza TCP

- TCPTimeout(ms) -> ustawia ilość ms po ilu ma zakończyć działanie funkcji w przypadku braku odpowiedzi

No i to tyle. UDP nie omówiłem, może ktoś się skusi i napisze o tym?

 

Dobrze, a teraz obiecana "gra" <strasznie w niej jest nakombinowane, przepraszam... po prostu miało być coś więcej, ale mi się odechciało pisać :P>

Mogą być jakieś stare wersje, bo nie wiem czy wszystko kompilowałem pod koniec pisania, więc jakby coś to piszcie ;]

Server

http://speedy.sh/GDHvU/server.exe

https://www.virustotal.com/file/190507a8c313e20deee24c4c3f0327cb0187b0b9bf5b72411127ee3b4fec8885/analysis/1349738722/

Klient

http://speedy.sh/b3MDH/game.exe

https://www.virustotal.com/file/60f4e14d1b1b98e705afac289edf0812bbfd098ff7d101c70ee908efae1836b5/analysis/1349738673/

 

Aha, byłbym zapomniał. Z góry przepraszam za wszelkie błędy, zarówno merytoryczne, jak i literówki. Postaram się całość przeczytać jeszcze raz wkleić do Worda i poprawić błędy, ale coś może być źle, więc w razie niepewności pisajcie!

 

Mam nadzieję, że się miło czytało i komuś to pomogło ;)

 

Sorry, że daję dopiero dzisiaj, ale szkoła, Borderlands i leń nie pozwoliły mi się wcześniej wziąć za napisanie samej treści tutoriala...

 

Pozdrawiam, hfaua B)

Opublikowano

Hmm, jak zrobić (I czy wogóle się da?) tak żeby przy wysłaniu komendy "/lol" po stronie klienta zostałby wykonany skrypt sprawdzający listę procesów która pojawiłaby się w gui serwera?

Opublikowano

Co się ma gdzie dziać? kto wysyła, kogo procesy i gdzie mają się pojawić? Bo Twoje pytanie można zinterpretować na parę sposobów

Opublikowano

Dokładnie chodzi o to, że gdybym np. ja wysłał ze swojego klienta komendę "/lol" to u kogoś innego sprawdzana jest lista procesów która jest później wysyłana do mojego klienta.

Opublikowano

No to robisz inputa w kliencie. Robisz pod jakiś button funkcję Send(guictrlread($input)), wysyłasz do 2 gościa, on dostaje tą wiadomość i sprawdza czy to jest /lol, jeśli tak, to wysyła Ci od siebie listę swoich procesów, jako jakieś pakiety, albo odpowiednio sformatowany string, Ty sobie to odbierasz i ew. parsujesz stringa/odczytujesz pakiety i dodajesz do GUI odpowiednie dane ;]

Opublikowano

Nie pisz "server" i "client", jesteśmy w Polsce.

Poza tym, dlaczego pętla while z warunkiem "true" się kończy?

Opublikowano

server i client.

Jak to się kończy? Gdzie, bo nie rozumiem?

Bo chodzi o to, że while (true) dopisujesz dalszy kod, chociaż pętla nie zawiera break, czyli wykonuje się ciągle, zatem kod po tej pętli nie ma prawa się wykonać.

Opublikowano

@UP

Formatowanie na MPC jest tragicznie mylące. Patrzysz na EndIf zamiast WEnd. Po pętli While...WEnd nie ma już żadnego kodu.

 

@TOPIC

Nawet fajnie działa. Pomijając fakt, że nie działa.

Po odzyskaniu focus'a, okno klienta nie dopuszcza żadnych więcej keystroke'ów.

Label'e klienta zawsze puste.

Ta sygnatura jest pusta.

Opublikowano

A no to to to wiem, ale tak jak pisałem, w połowie zdecydowałem się nie kontynuować, bo mi się odwidziało ;] Chociaż, może to poprawię w najbliższym czasie i dopiszę strzelanie, tak żeby zobaczyć jak to wyjdzie ;]

  • 4 miesiące temu...
Opublikowano

Sorka za odkop :(
Witam otóż zrobiłem server oraz client czatu tak jak z tutoriala:

Server:

$l = 0;nasza zmienna informująca nas ile klientów jest połączonych z serwerem
$max_clients = 10;maksymalna ilość połączonych klientów
Dim $client[$max_clients]

TCPStartup()
$Socket = TCPListen("127.0.0.1", 1337, $max_clients)
If $Socket <= 0 Then; sprawdzamy czy się udało stworzyć naszego socketa głównego
MsgBox(16, "Server", "Tworzenie socketa nasłuchującego się zjebało...")
TCPShutdown()
Exit
EndIf

While True
If $max_clients > $l Then;jesli jest jeszcze miejsce do połączenia się
$sock = TCPAccept($Socket);sprawdzamy czy ktoś się chce z nami łączyć
If $sock > -1 Then; jeśli tak
MsgBox(64, "Server", "Nawiązałem połączenie z nowym klientem!", 2);stosowna wiadomość na 2sec
$client[$l] = $sock;dodajemy do tablicy nasze gniazdo
$l += 1;zwiekszamy nasz licznik o 1
EndIf
EndIf

for $i = 0 to $l
$bufor = TCPRecv($client[$i], 2048)
if $bufor <> "" Then
for $j = 0 to $l
if $j = $i then ContinueLoop
TCPSend($client[$j], $bufor)
Next
EndIf
Next
WEnd

Client:

TCPStartup()
$Socket = TCPConnect("127.0.0.1", 1337)
If $Socket <= 0 Then
MsgBox(16, "Klient", "Nieudane połączenie z serwerem!")
TCPShutdown()
Exit
EndIf

GUICreate("Klient", 250, 300)
$czat = GUICtrlCreateEdit("", 5, 5, 240, 230)
$input = GUICtrlCreateInput("", 5, 240, 240, 20)
$button = GUICtrlCreateButton("Wyślij!", 5, 265, 240, 30)
GUISetState()

While True
$msg = GUIGetMsg()
If $msg = -3 Then Exit
If $msg = $button Then
TCPSend($Socket, GUICtrlRead($input))
GUICtrlSetData($czat, GUICtrlRead($czat) & @CRLF & GUICtrlRead($input))
EndIf


$bufor = TCPRecv($Socket, 2048);dłuzszych wiadomości nie przewidujemy
If $bufor <> "" Then
GUICtrlSetData($czat, GUICtrlRead($czat) & @CRLF & $bufor);dobra dobra, to ma tylko działać, kto będzie chciał zrobi sobie lepsze...
EndIf
WEnd

No i odpalam server plik client dałem koledze. Ok odpalam ja wyskakuje info z servera że połączono. Kolega włącza wyskakuje mu że nie można się połączyć. O co chodzi? gdy w kliencie i serverze zmieniam ip na inne niż localhost mi tez nie działa proszę o pomoc

Cipka - Najlepszy silnik na świecie. Działa z tłokiem każdej średnicy, wbudowana funkcja samosmarowania, odpalasz jednym palcem i co miesiąc sam się wymienia olej. Szkoda tylko że ma taki pojebany komputer pokładowy.

Opublikowano

bo w cliencie musisz ustawić swoje ip globalne, nie localhosta, lokalnego też nie

globalne ip, to te które widzi np. php

http://whatismyipaddress.com/

pamiętaj aby przekierować porty na twój lokalny adres ip

jak nie masz zmiennego to powinno być tak

 

 

$Socket = TCPConnect("188.33.88.107", 1337)

jak masz zmienne ip, to użyj domeny no-ip.com

Opublikowano

Mam zmienne lecz ta stronka no-ip.com mi nie wchodzi....
A dlaczego gdy wpisałem ip kolegi w serwerze i kliencie on włączył serwer stworzył się poprawnie to nie mogłem się połączyć do niego?

I czy zamiast mojego ip nie moge wpisać hostaname? (esprimo)

Cipka - Najlepszy silnik na świecie. Działa z tłokiem każdej średnicy, wbudowana funkcja samosmarowania, odpalasz jednym palcem i co miesiąc sam się wymienia olej. Szkoda tylko że ma taki pojebany komputer pokładowy.

Opublikowano

Download nie działa ;/ Jak możesz to reuploaduj je :D Wziąłem sobie kod który napisał MrKris7100. Pisałem wcześniej oryginalny konunikator pod swój serwer MC, ale źle to zrobiłem korzystałem z FTP xD Tutaj testuje to i ładnie działa, dorobie nicki, rejestracje lub logowanie do clienta (spróbuje przynajmniej, zrobiłem takie zwykłe logowanie i rejestracje z użyciem szyfrowania hasła) i może wyjdzie mi ładny komunikator :D Rób więcej takich tutoriali, mi bardzo pomogłeś !

Znasz mnie grałem na serwerach z nickiem lolo121. Jak nie wierzysz, daj serwer premium

 

48061.gif

Opublikowano

właśnie nie moge użyć hamachi bo nie będzie druga osoba go instalować i sie łączyć.... ja sie pytam czemu 2 osoba nie może sie połączyć do mnie ani ja do niej skoro wpisuje jej ip lub moje

Zadałem też 2 pytanie czy moge użyć hostname zamiast ip

Cipka - Najlepszy silnik na świecie. Działa z tłokiem każdej średnicy, wbudowana funkcja samosmarowania, odpalasz jednym palcem i co miesiąc sam się wymienia olej. Szkoda tylko że ma taki pojebany komputer pokładowy.

Opublikowano

@up

napisałem abyś przekierował ten port do swojego lokalnego adresu ip

zrobiłeś?

 

co do hostname, to one chyba nie są wskaznikiem, i jest dowolnie określany, więc nie sądzę aby się tak dało

Opublikowano

to dziwne bo kiedyś wgrałem koledze wirusa (Netbus) i łączyłem sie z nim przez jego hostname.... jak mam przekierować ten port??

Cipka - Najlepszy silnik na świecie. Działa z tłokiem każdej średnicy, wbudowana funkcja samosmarowania, odpalasz jednym palcem i co miesiąc sam się wymienia olej. Szkoda tylko że ma taki pojebany komputer pokładowy.

Opublikowano

jak masz router to wejdz do panelu admina, i tam masz port forwarding ip source = twoje lokalne ip, port 1337(ten ktory chcesz przekierowac) i usluga to tcp

jak beda 2 okienka do portu polaczone tym znaczkiem ~ to w obydwa wpisz ten sam port

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...