Java - sieć
Termin programowanie sieciowe odnosi się do pisania programów, które są wykonywane na wielu urządzeniach (komputerach), w których wszystkie urządzenia są połączone ze sobą za pomocą sieci.
Pakiet java.net interfejsów API J2SE zawiera zbiór klas i interfejsów udostępniających szczegóły komunikacji niskiego poziomu, co pozwala na pisanie programów, które koncentrują się na rozwiązaniu danego problemu.
Pakiet java.net zapewnia obsługę dwóch popularnych protokołów sieciowych -
TCP- TCP to skrót od Transmission Control Protocol, który pozwala na niezawodną komunikację między dwiema aplikacjami. Protokół TCP jest zwykle używany w protokole internetowym, który jest nazywany TCP / IP.
UDP - UDP to skrót od User Datagram Protocol, protokół bezpołączeniowy, który umożliwia przesyłanie pakietów danych między aplikacjami.
Ten rozdział daje dobre zrozumienie następujących dwóch tematów:
Socket Programming - Jest to najczęściej stosowana koncepcja w sieci i została bardzo szczegółowo wyjaśniona.
URL Processing- To byłoby omówione oddzielnie. Kliknij tutaj, aby dowiedzieć się więcej o przetwarzaniu adresów URL w języku Java.
Programowanie gniazd
Gniazda zapewniają mechanizm komunikacji między dwoma komputerami za pomocą protokołu TCP. Program klienta tworzy gniazdo na swoim końcu komunikacji i próbuje połączyć to gniazdo z serwerem.
Po nawiązaniu połączenia serwer tworzy obiekt gniazda na końcu komunikacji. Klient i serwer mogą teraz komunikować się poprzez zapisywanie i odczytywanie z gniazda.
Klasa java.net.Socket reprezentuje gniazdo, a klasa java.net.ServerSocket zapewnia programowi serwera mechanizm nasłuchiwania klientów i ustanawiania z nimi połączeń.
Podczas nawiązywania połączenia TCP między dwoma komputerami za pomocą gniazd występują następujące kroki -
Serwer tworzy instancję obiektu ServerSocket, wskazując numer portu, na którym ma się odbywać komunikacja.
Serwer wywołuje metodę accept () klasy ServerSocket. Ta metoda czeka, aż klient połączy się z serwerem na podanym porcie.
Gdy serwer czeka, klient tworzy instancję obiektu Socket, określając nazwę serwera i numer portu, z którym ma się połączyć.
Konstruktor klasy Socket próbuje połączyć klienta z określonym serwerem i numerem portu. Jeśli komunikacja jest ustanowiona, klient ma teraz obiekt Socket, który może komunikować się z serwerem.
Po stronie serwera metoda accept () zwraca odniesienie do nowego gniazda na serwerze, które jest połączone z gniazdem klienta.
Po ustanowieniu połączeń komunikacja może odbywać się za pomocą strumieni we / wy. Każde gniazdo ma zarówno OutputStream, jak i InputStream. OutputStream klienta jest połączony z InputStream serwera, a InputStream klienta jest połączony z OutputStream serwera.
TCP jest dwukierunkowym protokołem komunikacyjnym, dlatego dane mogą być przesyłane w obu strumieniach jednocześnie. Poniżej przedstawiono przydatne klasy zapewniające pełny zestaw metod do implementacji gniazd.
Metody klasy ServerSocket
Plik java.net.ServerSocket klasa jest używana przez aplikacje serwera do uzyskiwania portu i nasłuchiwania żądań klientów.
Klasa ServerSocket ma cztery konstruktory -
Sr.No. | Metoda i opis |
---|---|
1 | public ServerSocket(int port) throws IOException Próbuje utworzyć gniazdo serwera powiązane z określonym portem. Wyjątek występuje, jeśli port jest już powiązany z inną aplikacją. |
2 | public ServerSocket(int port, int backlog) throws IOException Podobnie jak w poprzednim konstruktorze, parametr backlog określa, ile klientów przychodzących ma być przechowywanych w kolejce oczekiwania. |
3 | public ServerSocket(int port, int backlog, InetAddress address) throws IOException Podobnie jak w poprzednim konstruktorze, parametr InetAddress określa lokalny adres IP do powiązania. InetAddress jest używany w przypadku serwerów, które mogą mieć wiele adresów IP, umożliwiając serwerowi określenie, na którym z jego adresów IP ma akceptować żądania klientów. |
4 | public ServerSocket() throws IOException Tworzy niezwiązane gniazdo serwera. Korzystając z tego konstruktora, użyj metody bind (), gdy będziesz gotowy do powiązania gniazda serwera. |
Jeśli konstruktor ServerSocket nie zgłasza wyjątku, oznacza to, że aplikacja została pomyślnie powiązana z określonym portem i jest gotowa na żądania klientów.
Poniżej przedstawiono niektóre typowe metody klasy ServerSocket -
Sr.No. | Metoda i opis |
---|---|
1 | public int getLocalPort() Zwraca port, na którym nasłuchuje gniazdo serwera. Ta metoda jest przydatna, jeśli przekazałeś 0 jako numer portu w konstruktorze i pozwoliłeś serwerowi znaleźć port za Ciebie. |
2 | public Socket accept() throws IOException Czeka na przychodzącego klienta. Ta metoda jest blokowana do momentu, gdy klient połączy się z serwerem na określonym porcie lub upłynie limit czasu gniazda, zakładając, że wartość limitu czasu została ustawiona przy użyciu metody setSoTimeout (). W przeciwnym razie ta metoda blokuje się na czas nieokreślony. |
3 | public void setSoTimeout(int timeout) Ustawia wartość limitu czasu określającą, jak długo gniazdo serwera czeka na klienta podczas accept (). |
4 | public void bind(SocketAddress host, int backlog) Wiąże gniazdo z określonym serwerem i portem w obiekcie SocketAddress. Użyj tej metody, jeśli utworzono wystąpienie ServerSocket przy użyciu konstruktora bez argumentów. |
Gdy ServerSocket wywołuje accept (), metoda nie zwraca, dopóki klient nie nawiąże połączenia. Po nawiązaniu połączenia przez klienta ServerSocket tworzy nowe Socket na nieokreślonym porcie i zwraca odwołanie do tego nowego Socket. Między klientem a serwerem istnieje teraz połączenie TCP i można rozpocząć komunikację.
Metody klasy gniazda
Plik java.net.Socketclass reprezentuje gniazdo, którego klient i serwer używają do komunikacji między sobą. Klient uzyskuje obiekt Socket, tworząc jego instancję, podczas gdy serwer uzyskuje obiekt Socket ze zwracanej wartości metody accept ().
Klasa Socket ma pięć konstruktorów, których klient używa do łączenia się z serwerem -
Sr.No. | Metoda i opis |
---|---|
1 | public Socket(String host, int port) throws UnknownHostException, IOException. Ta metoda próbuje połączyć się z określonym serwerem na określonym porcie. Jeśli ten konstruktor nie zgłosi wyjątku, połączenie powiedzie się, a klient zostanie połączony z serwerem. |
2 | public Socket(InetAddress host, int port) throws IOException Ta metoda jest identyczna z poprzednim konstruktorem, z tą różnicą, że host jest oznaczony przez obiekt InetAddress. |
3 | public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. Łączy się z określonym hostem i portem, tworząc gniazdo na lokalnym hoście pod określonym adresem i portem. |
4 | public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. Ta metoda jest identyczna z poprzednim konstruktorem, z tą różnicą, że host jest oznaczony przez obiekt InetAddress zamiast String. |
5 | public Socket() Tworzy niepołączone gniazdo. Użyj metody connect (), aby podłączyć to gniazdo do serwera. |
Gdy konstruktor Socket zwraca, nie tworzy po prostu wystąpienia obiektu Socket, ale w rzeczywistości próbuje połączyć się z określonym serwerem i portem.
Poniżej wymieniono niektóre interesujące metody w klasie Socket. Zauważ, że zarówno klient, jak i serwer mają obiekt Socket, więc te metody mogą być wywoływane zarówno przez klienta, jak i przez serwer.
Sr.No. | Metoda i opis |
---|---|
1 | public void connect(SocketAddress host, int timeout) throws IOException Ta metoda łączy gniazdo z określonym hostem. Ta metoda jest potrzebna tylko wtedy, gdy tworzysz wystąpienie Socket przy użyciu konstruktora bez argumentów. |
2 | public InetAddress getInetAddress() Ta metoda zwraca adres innego komputera, do którego jest podłączone to gniazdo. |
3 | public int getPort() Zwraca port, do którego jest przypisane gniazdo na komputerze zdalnym. |
4 | public int getLocalPort() Zwraca port, z którym jest powiązane gniazdo na komputerze lokalnym. |
5 | public SocketAddress getRemoteSocketAddress() Zwraca adres zdalnego gniazda. |
6 | public InputStream getInputStream() throws IOException Zwraca strumień wejściowy gniazda. Strumień wejściowy jest połączony ze strumieniem wyjściowym zdalnego gniazda. |
7 | public OutputStream getOutputStream() throws IOException Zwraca strumień wyjściowy gniazda. Strumień wyjściowy jest połączony ze strumieniem wejściowym zdalnego gniazda. |
8 | public void close() throws IOException Zamyka gniazdo, przez co ten obiekt Socket nie może już łączyć się ponownie z żadnym serwerem. |
Metody klasy InetAddress
Ta klasa reprezentuje adres protokołu internetowego (IP). Oto przydatne metody, których potrzebujesz podczas programowania w gniazdach -
Sr.No. | Metoda i opis |
---|---|
1 | static InetAddress getByAddress(byte[] addr) Zwraca obiekt InetAddress z podanym surowym adresem IP. |
2 | static InetAddress getByAddress(String host, byte[] addr) Tworzy InetAddress na podstawie podanej nazwy hosta i adresu IP. |
3 | static InetAddress getByName(String host) Określa adres IP hosta na podstawie nazwy hosta. |
4 | String getHostAddress() Zwraca ciąg adresu IP w prezentacji tekstowej. |
5 | String getHostName() Pobiera nazwę hosta dla tego adresu IP. |
6 | static InetAddress InetAddress getLocalHost() Zwraca hosta lokalnego. |
7 | String toString() Konwertuje ten adres IP na ciąg. |
Przykład klienta gniazda
Poniższy GreetingClient to program kliencki, który łączy się z serwerem za pomocą gniazda i wysyła powitanie, a następnie czeka na odpowiedź.
Przykład
// File Name GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient {
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Przykład serwera gniazd
Poniższy program GreetingServer jest przykładem aplikacji serwera, która używa klasy Socket do nasłuchiwania klientów na porcie o numerze określonym przez argument wiersza polecenia -
Przykład
// File Name GreetingServer.java
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
+ "\nGoodbye!");
server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) {
int port = Integer.parseInt(args[0]);
try {
Thread t = new GreetingServer(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Skompiluj klienta i serwer, a następnie uruchom serwer w następujący sposób -
$ java GreetingServer 6066
Waiting for client on port 6066...
Sprawdź program klienta w następujący sposób -
Wynik
$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!