SIK05.rst

Sieci Komputerowe

Programowanie socketów. Różne języki *

Java

Przykład, server zamieniający komunikat na wielkie litery:

    import java.io.*;
    import java.net.*;

    class tcp
    {
            public static void main(String argv[]) throws Exception
            {
        String clientSentence;
        String capitalizedSentence;
        ServerSocket welcomeSocket = new ServerSocket(6789);

        while(true)
        {
            Socket connectionSocket = welcomeSocket.accept();

            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));

            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

            clientSentence = inFromClient.readLine();

            System.out.println("Received: " + clientSentence);

            capitalizedSentence = clientSentence.toUpperCase() + '\n';

            outToClient.writeBytes(capitalizedSentence);
        }
    }
}

Klient, przykład:

import java.io.*;
import java.net.*;

/**
* Usage:input a string, server will return a value.
**/

class TCPClient {
        public static void main(String argv[]) throws Exception {
                String sentence;
                String modifiedSentence;

                BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));

                Socket clientSocket = new Socket("localhost", 6789);

                DataOutputStream outToServer = new

                DataOutputStream(clientSocket.getOutputStream());

                BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                sentence = inFromUser.readLine();

                outToServer.writeBytes(sentence + '\n');

                modifiedSentence = inFromServer.readLine();

                System.out.println("FROM SERVER: " + modifiedSentence);

                clientSocket.close();
        }
}

Więcej przykładów w Javie:

Zadanie

Zadanie (5 pkt)

Zadaniem Państwa jest napisanie programu grającego w grę kółko i krzyżyk na planszy 5x5, gdzie wygrywającymi układami są proste poziome, pionowe oraz przekątne. Państwa program gra z komputerem a w przypadku remisu na koniec gry, jest on traktowany jak Państwa wygrana.

Serwer za każdym połączeniem rozgrywa po 200 gier i zadaniem Państwa programu jest wygranie co najmniej 175 z nich.

Klient musi komunikować się z serwerem zgodnie z poniższym protokołem. Uwaga! można wykorzystać program netcat do połączenia z serwerem w celu sprawdzenia jak on działa.

Na powitanie Serwer przesyła komunikat:

WELCOME, STATE YOUR NAME

I oczekuje od klienta na wysłanie Swojego loginu w postaci

LOGIN imie_nazwisko

Każdy poprawnie odebrany i sparsowany komunikat przez serwer potwierdzany jest komunikatem OK, każdy błędny komunikat oznaczany jest przez serwer poprzez przesłanie do klienta ERROR.

Następnie serwer czeka na spis ruchów użytkownika w postaci:

MOVE nr między 0 a 24

Uwaga! Planszę traktujemy jako zapisaną w postaci - pierwszy wiersz to pola 0..4, drugi wiersz pola 5..9, itd.

W przypadku wysłania ruchu na już zajęte pole otrzymujemy komunikat ERROR.

W odpowiedzi na ruch klienta wysyłany jest albo ruch przeciwnika (który gra całkowicie losowo) postaci:

OPPONENT nr między 0 a 24

Albo komunikat o wygranej

WIN

albo (po komunikacie OPPONENT) komunikat o przegranej

LOST

Uwaga! Oznacza to że w przypadku przegranej otrzymujemy od serwera trzy komunikaty pod rząd !!

Po wygranej lub przegranej przesyłany jest także komunikat o rozpoczęciu nowej gry

NEW GAME

I następnie serwer oczekuje na ruch użytkownika w nowej grze.

Po zakończeniu 50 gier użytkownik powiadamiany jest o wykonaniu zadania - komunikat "SUCCESS" lub porażce - komunikat "FAILED" i serwer kończy komunikację z użytkownikiem (zamyka socket).

W przypadku sukcesu państwa login zapisywany jest do pliku.

SERVER działa pod adresem: 150.254.68.149, na porcie 8787. Uwaga! Serwer jest dostępny tylko z sieci wydziałowej, w przypadku połączenia z domu państwa sieć lokalna pewnie nie pozwoli na nawiązanie skutecznej komunikacji. Implementacja serwera do testów lokalnych dostępna jest tutaj:

uruchomienie:

javac ttt.java
java ttt

Może posłużyć do lokalnych testów, ale ostatecznie w celu uzyskania punktów należy połączyć się z serwerem prowadzącego!

Aby sprawdzić czy udało nam się wykonać zadanie można wejść na stronę i odszukać siebie w pliku

Streaming

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

oraz RTSP

implementacje RTSP w javie można znaleźć np. tutaj

Co nie znaczy, że nie możemy przesyłać ramek video korzystając z innych protokołów, np. 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

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

import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacv.*;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class Stream  {

    public static BufferedImage getBufferedImage(Frame frame) {
        OpenCVFrameConverter.ToIplImage toIplImage = new OpenCVFrameConverter.ToIplImage();
        Java2DFrameConverter frameConverter = new Java2DFrameConverter();
        return frameConverter.convert(frame);
    }

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

        FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("http://192.167.1.100:8080/video");
        frameGrabber.start();

        BufferedImage image = getBufferedImage(frameGrabber.grabFrame());

        CanvasFrame canvasFrame = new CanvasFrame("Camera");
        canvasFrame.setCanvasSize(image.getWidth(), image.getHeight());

        int czy = 1000;
        while (canvasFrame.isVisible() && (image != null)) {
            image = getBufferedImage(frameGrabber.grabFrame());
            canvasFrame.showImage(image);
        }

        frameGrabber.stop();
        canvasFrame.dispose();
        System.exit(0);
    }
}

Przesyłanie plików binarnych w sieci

Serwer odbiera plik jako strumień bitów:

    import java.io.*;
    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();

        System.out.println("Accepted connection : " + sock);

                (new Thread() {
                    public void run() {
                        try {
                            InputStream is = sock.getInputStream();
                            byte[] mybytearray = new byte[1000000000];
                            String name = new BufferedReader(new InputStreamReader(is))
                                    .readLine();
                            System.out.println(name);
                            OutputStream os = sock.getOutputStream();
                            String mes = "ok\n";
                            os.write(mes.getBytes(Charset.forName("UTF-8")));
                            FileOutputStream fos = new FileOutputStream(name + ".png");
                            BufferedOutputStream bos = new BufferedOutputStream(fos);

                            // read 4 bytes containing the file size
                            byte[] bSize = new byte[4];
                            int offset = 0;
                            while (offset < bSize.length) {
                                int bRead = is.read(bSize, offset, bSize.length - offset);
                        offset += bRead;
                            }
                            // Convert the 4 bytes to an int
                            int fileSize;
                            fileSize = (int) (bSize[0] & 0xff) << 24
                                    | (int) (bSize[1] & 0xff) << 16
                                    | (int) (bSize[2] & 0xff) << 8
                                    | (int) (bSize[3] & 0xff);

                                    // buffer to read from the socket
                            // 8k buffer is good enough
                    byte[] data = new byte[8 * 1024];

                    int bToRead;
                            while (fileSize > 0) {
                                // make sure not to read more bytes than filesize
                                if (fileSize > data.length) bToRead = data.length;
                                else bToRead = fileSize;
                                int bytesRead = is.read(data, 0, bToRead);
                                if (bytesRead > 0) {
                                    bos.write(data, 0, bytesRead);
                                    fileSize -= bytesRead;
                                }
                            }
                            bos.close();

                            is.close();
                            bos.close();
                            sock.close();
                        } catch (Exception e) {
                            System.out.println(e.getStackTrace());
                        }
                    }
                }).start();
            }
        }
    }

Klient przesyła plik bitowo:

import java.io.*;
import java.net.Socket;

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));
                  System.out.print("Enter name : ");
                  String input = br.readLine();
                  input += '\n';
                  OutputStream os = sock.getOutputStream();
                  os.write(input.getBytes("UTF-8"));
                  os.flush();
                  String mes = new BufferedReader(new InputStreamReader(sock.getInputStream()))
                  .readLine();

                    System.out.println(mes);

        File myFile = new File("saved.png");
        byte[] mybytearray = new byte[(int) myFile.length()];
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));

        int fSize = (int) myFile.length();
        // Send the file's size
        byte[] bSize = new byte[4];
        bSize[0] = (byte) ((fSize & 0xff000000) >> 24);
        bSize[1] = (byte) ((fSize & 0x00ff0000) >> 16);
        bSize[2] = (byte) ((fSize & 0x0000ff00) >> 8);
        bSize[3] = (byte) (fSize & 0x000000ff);
        // 4 bytes containing the file size
        os.write(bSize, 0, 4);

        int size = bis.read(mybytearray, 0, mybytearray.length);
        sock.getOutputStream().write(mybytearray, 0, size);
        sock.getOutputStream().flush();
        bis.close();
        os.close();
        sock.close();
    }
}

Zadanie (5 pkt)

Prowadzący uruchomi na swojej komórce serwer streamujący obraz.

adres streamingu-> IP: 10.100.6.158 port: 8383.

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:

Wykorzystaj plik FileClient.java do przesłanie do serwera podanego przez prowadzącego pliku ze zdjęciem.

UWAGA! proszę przesłać po rozwiązaniu zadania pusty plik poprzez serwis do wysyłania zadań.

Żebym mógł Państwu wpisać punkty.

*

Wykorzystano materiały z:

https://gist.github.com/roroco/11131088