Клиентские сокеты по протоколу TCP/IP в Java

Клиентские сокеты по протоколу TCP/IP в JavaСокеты по протоколу ТСР/IP служат для реализации надежных двунаправленных, постоянных, двухточечных, потоковых соединений между хостами в Интернете.

Сокет может служить для подключения системы ввода-вывода в Java к другим программам, которые могут находиться как на локальной машине, таки на любой другой машине в Интернете.

В Java поддерживаются две разновидности сокетов по протоколу ТСР /IP: один - для серверов, другой - для клиентов.

Класс ServerSocket служит "приемником", ожидая подключения клиентов прежде, чем предпринять какие-нибудь действия. Иными словами, класс ServerSocket предназначен для серверов, тогда как класс Socket - для клиентов.

Он служит для подключения к серверным сокетам и инициирования обмена данными по сетевому протоколу. Клиентские сокеты чаще всего применяются в прикладных программах на Java.

При создании объекта типа Socket неявно устанавливается соединение клиента с сервером.

Выявить это соединение нельзя никакими методами или конструкторами. Ниже перечислены два конструктора класса Socket, предназначенные для создания клиентских сокетов.

//  ,    _  
Socket(String _, int ) throws UnknownHostException, IOException

//  ,      InetAddress   
Socket(InetAddress IP-, int ) throws IOException

В классе Socket определяется ряд методов экземпляра. Например, объект типа Socket может быть просмотрен в любой момент для извлечения сведений о связанных с ним адресе и порте. Для этого применяются методы, перечисленные ниже.

  • InetAddress getInetAddress() - возвращает объект типа InetAddress, связанный с объектом типа Socket. Если же сокет не подключен, возвращается значение null
  • int getPort() - возвращает удаленный порт, к которому привязан вызывающий объект типа Socket. Если же сокет не привязан, возвращается нулевое значение
  • int getLocalPort() - возвращает локальный порт, к которому привязан вызывающий объект типа Socket. Если же сокет не привязан, возвращается значение -1

Для доступа к потокам ввода-вывода, связанным с классом Socket, можно вос­пользоваться методами getInputStream() и getOuptutStream(), перечислен­ными ниже.

Каждый из этих методов может сгенерировать исключение типа IOException, если сокет оказался недействительным из-за потери соединения.

Эти потоки ввода-вывода используются для передачи и приема данных таким же образом, как и потоки ввода-вывода.

  • InputStream getInputStream() throws IOException - возвращает объект типа InetAddress, связанный с вызывающим сокетом
  • OutputStream getOutputStream() throws IOException - возвращает объект типа OutputStream, связанный с вызывающим сокетом

Имеется и ряд других методов, в том числе метод connect(), позволяющий указать новое соединение; метод isConnected(), возвращающий логическое зна­чение true, если сокет подключен к серверу; метод isBound(), возвращающий ло­гическое значение true, если сокет привязан к адресу; а также метод isClosed(), возвращающий логическое значение true, если сокет закрыт.

Чтобы закрыть со­кет, достаточно вызвать метод close(). Закрытие сокета приводит также к закры­тию связанных с ним потоков ввода-вывода.

Начиная с версии JDК 7 класс Socket реализует также интерфейс AutoCloseabe. Это означает, что управление соке­ том можно организовать в блоке оператора try с ресурсами.

Приведенная ниже программа служит простым примером применения класса Socket. В этой программе устанавливается соединение с портом "whois" (номер 43) на Tcinet-cepвepe, посылается аргумент командной строки через сокет, а затем вы­водятся возвращаемые данные.

Tcinet-cepвep пытается интерпретировать аргу­мент как зарегистрированное доменное имя Интернета, а затем возвращает IР-адрес и контактную информацию из веб-сайта, найденного по этому доменному имени.

//      Java

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

class Whois {

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

    //     - tcinet.ru
    //   43

    Socket s = new Socket("whois.tcinet.ru", 43);
    
    //   -
    InputStream in = s.getInputStream();
    OutputStream out = s.getOutputStream();

    //   

    String str = (args.length == 0 ? "pro-java.ru" : args[0]) + "\n";

    //    

    byte buf[] = str.getBytes();

    //  

    out.write(buf);

    //       
    
    while((c = in.read()) != -1) {
        System.out.print((char) c);
    }

    s.close();
    }
}

Если запросить, например, сведения об адресе pro-java.ru, то будет получен результат, аналогичный следующему:

% By submitting a query to RIPN's Whois Service
% you agree to abide by the following terms of use:
% http://www.ripn.net/about/servpol.html#3.2 (in Russian) 
% http://www.ripn.net/about/en/servpol.html#3.2 (in English).

domain:        PRO-JAVA.RU
nserver:       dns2.fastdns24.org.
nserver:       dns3.fastdns24.eu.
nserver:       dns4.fastdns24.link.
nserver:       dns.fastdns24.com.
state:         REGISTERED, DELEGATED, VERIFIED
person:        Private Person
registrar:     REGRU-RU
admin-contact: http://www.reg.ru/whois/admin_contact
created:       2013-04-30T10:36:21Z
paid-till:     2018-04-30T11:36:21Z
free-date:     2018-05-31
source:        TCI

Last updated on 2017-04-20T11:56:32Z

Эта программа на Java действует следующим образом. Сначала в ней создается объект типа Socket, обозначающий сокет и задающий имя хоста "whois.tcinet.ru" и номер порта 43.

Затем в сокете открываются потоки ввода-вывода. Далее формируется символьная строка, содержащая имя веб-сайта, сведения о котором требуется получить.

Если веб-сайт не указан в командной строке, то выбирается имя хоста "pro-java.ru". Эта символьная строка преобразуется в массив байтов и направляется в сеть через сокет.

После этого ответ читается из сокета, а резуль­тат выводится на экран. И наконец, сокет закрывается, а вместе с ним и потоки ввода-вывода. В данном примере сокет закрывается вручную в результате вызова метода close().

Если же используется комплект версии JDК 7, то для автомати­ческого закрытия сокета можно организовать блок оператора try с ресурсами. В качестве примера ниже приведен другой способ написать метод main() из рас­сматриваемой здесь программы, чтобы закрывать сокет автоматически.

//    try     

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

class Whois {

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

    //     - tcinet.ru
    //   43

    try ( Socket s = new Socket("whois.tcinet.ru", 43) ) {
    
        //   -
        InputStream in = s.getInputStream();
        OutputStream out = s.getOutputStream();

        //   

        String str = (args.length == 0 ? "pro-java.ru" : args[0]) + "\n";

        //    

        byte buf[] = str.getBytes();

        //  

        out.write(buf);

        //       
    
        while((c = in.read()) != -1) {
            System.out.print((char) c);
        }
        }

    //   
    }
}

В своем прикладном коде следует уделить внимание автоматическому управлению сетевыми ресурсами, по­скольку это более рациональный и гибкий подход.

Следует также иметь в виду,что в данной версии программы исключения все еще генерируются в теле метода main(), но их можно было бы перехватывать и обрабатывать, добавив операторы catch в конце блока оператора try с ресурсами.

Интересное видео на сегодня:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *