Sieci Komputerowe

Przesyłanie plików. Streaming *

Streaming

Do przesyłania danych video najczęściej stosuje się protokoły warstwy aplikacji wspomagające transmisje danych video i dźwięku RTS

oraz RTSP

Co nie znaczy, że nie możemy przesyłać ramek video korzystając z pakietów UDP lub też protokołu HTTP.

Kamera

Do utworzenia serwera video na naszym telefonie może posłużyć np aplikacja IP WebCam

Z reguły rozwiązania takie pozwalają na przesyłanie video tylko w sieci lokalnej, ale nadal dają duże możliwości. Aplikacja ta wykorzystuje protokół HTTP do przesyłania Video.

Klient

Pobierz jary do biblioteki OpenCV

Prosty klient korzystający z biblioteki OpenCV do odbioru ramek Video:

import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.cpp.opencv_core.IplImage;

/**
*
*
*/
public class JavaCv  {


public static void main(String[] args) throws Exception {
        OpenCVFrameGrabber frameGrabber = new OpenCVFrameGrabber("http://192.168.0.2:8080/video?dummy=param.mjpg");
        frameGrabber.setFormat("mjpeg");
        frameGrabber.start();
        IplImage iPimg = frameGrabber.grab();
        CanvasFrame canvasFrame = new CanvasFrame("Camera");
        canvasFrame.setCanvasSize(iPimg.width(), iPimg.height());

        while (canvasFrame.isVisible() && (iPimg = frameGrabber.grab()) != null) {
                canvasFrame.showImage(iPimg);
        }
        frameGrabber.stop();
        canvasFrame.dispose();
        System.exit(0);
        }
}

Przesyłanie plików

Serwer odbiera plik jako strumień bajtów:

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;

public class FileSerwer {

public static void main(String[] args) throws IOException {
        ServerSocket servsock = new ServerSocket(8888);
        while (true) {
                Socket sock = servsock.accept();
                InputStream is = sock.getInputStream();
                byte[] mybytearray = new byte[1000000];
                FileOutputStream fos = new FileOutputStream("nowy.png");
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                int bytesRead = is.read(mybytearray, 0, mybytearray.length);
                bos.write(mybytearray, 0, bytesRead);
                bos.close();
                sock.close();
}
        }
}

Klient przesyła plik:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.stream.Collectors;

public class FileClient {

        public static void main(String[] argv) throws Exception {

                Socket sock = new Socket("127.0.0.1", 8888);
                sock.setTcpNoDelay(true);
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                //Przesłanie pliku
                File myFile = new File("co.png");
                byte[] mybytearray = new byte[(int) myFile.length()];
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
                //plik do tablicy bajtow
                bis.read(mybytearray, 0, mybytearray.length);
                //tablica do serwera
                os.write(mybytearray, 0, mybytearray.length);
                os.close();
                sock.close();
        }
}

Zadanie (10 pkt)

Prowadzący uruchomi na swojej komórce serwer streamujący obraz. Twoim zadaniem jest napisać kod, który wykona Twoje zdjęcie oraz prześle je do prowadzącego na podany adres.

Proponuję wykorzystać metodę taką, żeby zasłonić kamerę (wykryć czarne piksele) i zachowywać ramkę następującą ileś po tym zasłonięciu. Do wykrycia koloru piksela można wykorzystać:

Do zapisuj ramki na dysk:

Klient powinien przesłać do serwera podanego przez prowadzącego plik ze zdjęciem.

Klient powinien najpierw przesłać jako tekst nazwisko, na które serwer po odebraniu odpowie komunikatem "OK", następnie powienien być przesłany plik ze zdjęciem.

Kod klienta proszę przesłać przez stronę:

Projekt

Projektem jest stworzenie serwera i klienta dla uproszczonej wersji gry zatacka .

W grze brać będzie udział 8 graczy. Plansza, na której odbywa się gra ma mieć wielkość 100x100 pól. Gracze pojawiają się na planszy w losowych miejscach. Każdy gracz okupuje na początku pojedyncze pole gry, następnie w każdej rundzie przesuwa się na sąsiednie pole zostawiając za sobą ślad. Gracz przegrywa jeżeli wejdzie w ścianę lub w ślad pozostawiony przez któregoś z graczy. Na początku serwer przesyła do wszystkich graczy ich numer ID oraz listę początkową ustawienia graczy. Gracze odpowiadają kierunkiem w którym chcą wystartować. Gra odbywa się w turach. Tura trwa 500ms. Co 500 ms serwer przesyła graczom listę aktywnych graczy oraz postać planszy. Gracze odpowiadają serwerowi kierunkiem ruchu w tej turze. W przypadku braku odpowiedzi utrzymywany jest kierunek z rundy poprzedniej (za wyłączeniem początku gry, gdy gracz musi podać kierunek).

Plansza jest numerowana od pola (1,1) lewe górne pole do (100,100) prawe dolne pole.

Serwer każdą poprawną komendę potwierdza komunikatem "OK", każdą niepoprawną oznacza wysyłając "ERROR".

Protokół:

W momencie połączenia serwer przesyła do użytkownika komunikat (nie używamy polskich znaków!!)

S: CONNECT

Przed włączeniem się do gry każdy gracz musi się "zalogować" podając swój login (niepusty ciąg znaków)

C: LOGIN <login>

W momencie, gdy 8 osób włączy się do gry, gra zostaje uruchomiona a serwer przesyła do zawodników komunikat START

S: START <your_ID>

i zaraz po nim

S: PLAYERS <lista współrzędnych graczy>

Następnie każdy użytkownik wybiera początkowy kierunek ruchu w formie

C: BEGIN <move>

gdzie <move> to jedno z S (rosnąco po y), N (malejąco po y), E (rosnąco po x), W (malejąco po x)

Gra rozpoczyna się komunikatem

S: GAME

Co 500 ms serwer przesyła do aktywnych graczy stan planszy w postaci

S: BOARD <lista_pól>

gdzie lista pól to opis planszy od 1,1 do 100,100 wierszami, gdzie numer 0 oznacza wolne pole, a numery od 1 do 8 oznaczają ślady graczy o ID od 1 do 8.

W każdej turze serwer oczekuje od klienta, w którą stronę chce się udać

C: MOVE <move>

Gdzie <move> to jedno z (R (skręć w prawo), L (skręć w lewo), S (prosto))

W przypadku przegranej serwer przesyła do gracza komunikat

S: LOST <pozycja>

Gdzie pozycja to numer pozycji na której ukończył grę. W przypadku remisu przyznawane są pozycje ex-aequo. Od tego momentu serwer przestaje klientowi wysyłać stan planszy.

Gracz, który zostaje jako ostatni otrzymuje komunikat

S: WIN

Po zakończeniu jednej gry uruchamiana jest następna runda, przesyłany jest komunikat o kolejnej rundzie

S: ROUND <nr_rundy>

Po którym następuje komunikat

S: PLAYERS <lista współrzędnych graczy>

Gdy rozegrane zostanie 5 gier, rozgrywka zostaje zakończona i wszyscy gracze otrzymują komunikat.

S: ENDGAME <uszeregowane_loginy_graczy_od wygranego do ostatniego miejsca>

np. ENDGAME s123456 s654321 s123987 ...

Rannking tworzony jest następująco: sumowane są pozycje graczy w poszczególnych grach, gracz o najmniejszej sumie wygrywa. W przypadku remisu wyższą pozycję uzyskuje gracz o niższym ID.

Następnie serwer kończy działanie.

Dodatkowe założenia:

* w przypadku, gdy klient nie odpowiada przez 3 sekundy jest wyrzucany z gry,
* w przypadku gdy klient wyśle powyżej 100 złych komunikatów, jako pojedyncza odpowiedź jest on wyrzucany z gry

Państwa serwer i klient musi implementować powyższy protokół komunikacji. Dodatkowo mają Państwo za zadanie stworzyć drugi program kliencki, którego celem jest wywołanie błędu, oszukanie, lub spowodowanie błędu serwera. Wszelkie sposoby (dozwolone prawnie), w tym ataki na serwer są akceptowane. Program ten jednak musi się najpierw z sukcesem zalogować na serwerze (wysłac poprawnie przynajmniej komunikat LOGIN i odebrać komunikat OK).

Programu powinny logować informację,które sprawią że w przypadku sytuacji konfliktowych będziemy w stanie rozstrzygnąć kto popełnił błąd (serwer, czy aplikacja klienta).

Serwer musi zapisywac (logowac) do pliku całą komunikacje pomiedzy nim a klientami.

Każdy komunikat musi być zakończony znakiem końca linii!

Program może być wykonany w dowolnym języku programowania ale musi wykorzystywać do komunikacji protokół TCP. Termin wykonania zadania: 10.06.2017.

*

Wykorzystano materiały z:

https://www.youtube.com/watch?v=3_GNE0t_VzY

http://www.rgagnon.com/javadetails/java-0542.html