Сокеты TCP/IP Лекция 2. 2. Понятие сокета Если требуется получить доступ к сетевым операциям низкого уровня (класс URL обеспечивает выполнение только сетевых операций высокого уровня), в программе следует использовать класс Socket. Протокол TCP/IP (базовый протокол сети Internet) основывается на соединениях, устанавливаемых между двумя компьютерами, обычно называемых клиентом и сервером. Множество приложений для Internet базируются на использовании протокола TCP/IP. 3. Понятие сокета Протокол TCP/IP построен на основе использования сетевых соединений – соединение сначала должно быть установлено, затем осуществляется передача данных, после чего оно разрывается. Все эти действия напоминают обычный телефонный звонок. Существует и другой тип сетевого протокола – UDP (User Datagram Protocol). Он работает без предварительной установки сетевого соединения и больше напоминают процедуру отправки обычной телеграммы. 4. Сокеты TCP Процесс соединения двух компьютеров по сети определяет понятие сокета. TCP/IP сокеты используются для реализации надежных поточных соединений между компьютерами в сети Internet. Соединение с использованием TCP/IP сокетов является постоянным и определяется в двух направлениях. C помощью TCP/IP сокетов можно программировать подключение систем ввода/вывода к программам, расположенным на любом компьютере в сети. Помимо этого TCP/IP сокеты позволяют реализовать подключение и к локальной машине. 5. Сокеты TCP Зачастую на практике для соединения по TCP/IP сокетам на компьютерах открываются определенные порты, что позволяет расширить и разграничить канал подключения компьютера. После этого одна из программ запускается и переводится в режим прослушивания заданного порта. При подключении к данному порту клиентской программы выполняется их соединение для передачи/получения какой-либо информации. 6. Сокеты TCP Сокеты TCP являются важным понятием в программировании. С их помощью разработчик может создавать свои прикладные протоколы, отличные от HTTP и FTP. Сокеты (socket) – это описатель сетевого соединения с другим приложением. Сокет TCP использует протокол TCP, наследуя все свойства этого протокола. Для создания TCP необходима следующая информация: IP-адрес локальной машины; Номер порта TCP, который использует приложение на локальной машине; IP-адрес машины, с которой устанавливается связь; Номер порта TCP, на который отзывается приложение, ожидающее установления связи. 7. Программа-сервер Программа – сервер выполняет следующие шаги: Ожидание подключения клиента; Установка соединения с клиентом; Отправка клиенту сообщения; Разрыв соединения и завершение программы. 8. Программа-клиент Программа-клиент выполняет следующие действия: Подключение к серверу. Ожидание получения сообщения от сервера. Отображение полученного сообщения пользователю. Разрыв соединения с сервером. 9. Программирование TCP/IP сокетов в Java В Java в пакете java.net определены два класса ServerSocket и Socket, реализующие программирование TCP/IP сокетов. Класс ServerSocket определяет серверное соединение и выполняет функции прослушивания заданного порта. Иначе говоря, сетевой сокет ServerSocket ожидает соединения с клиентом, прослушивая определенный порт. С другой стороны, сетевой сокет Socket выполняет функции клиентского соединения, т.е. с его помощью реализуется подключение к определенно заданному адресу, инициализация различных протоколов и передача или получение данных. 10. Серверный сокет Для того, чтобы создать новый серверный сокет, необходимо объявить экземпляр класса ServerSocket, используя один из его конструкторов, например: ServerSocket srvsocket=new ServerSocket(numberPort); Серверные приложения запускаются на локальном компьютере. В качестве параметра представленный конструктор класса ServerSocket принимает номер порта, который впоследствии и будет прослушиваться программой. 11. Методы серверного сокета Для экземпляра класса ServerSocket определена группа методов, управляющих поведением серверного соединения и информирующих о его параметрах. Использование метода getInetAddress() данного класса позволяет получить объект InetAddress, описывающий параметры адреса компьютера, на котором запущен данный серверный сокет. С помощью метода getLocalPort() класса ServerSocket определяется номер порта прослушивания. 12. Исключения В процессе работы с сетевыми сокетами возможно возникновение ряда ошибочных ситуаций. В основном объекты ServerSocket и Socket могут генерировать исключения ошибки ввода/вывода IOException и ошибки системы безопасности (если она определена на компьютере) SecurityException. 13. Фрагмент программысервера import java.net.*; import java.io.*; public class MyServer { int port=4; ServerSocket srvSocket; boolean flag=true; public MyServer() { try { srvSocket=new ServerSocket(port); 14. Фрагмент программысервера (продолжение) System.out.println("InetAddress="+srvSocket.getInetAddress()); System.out.println("Port="+srvSocket.getLocalPort()); System.out.println("My Server YES "); } catch(IOException e) { System.out.println("Error connection"+e.getMessage()); System.exit(0); } … 15. Клиентский сокет Однако объект класса ServerSocket позволяет только прослушивать определенный порт компьютера. Любые процессы передачи данных через этот сокет осуществляются с использованием объекта Socket. Объект Socket возвращается методом accept() класса ServerSocket, что обеспечивает сам процесс прослушивания порта: Socket clientsocket=srvsocket.accept(); 16. Клиентский сокет в программе-сервере Объявленный экземпляр srvsocket класса серверного сокета ServerSocket осуществляет только лишь резервирование определенного заданного порта. Для прослушивания данного порта необходимо будет воспользоваться методом accept() того класса, который возвращает объект Socket. Класс ServerSocket определяет процесс прослушивания порта, а объект Socketпроцесс передачи данных через него. 17. Фрагмент программысервера … Socket clientSocket; while (flag) { if (srvSocket==null) return; try { clientSocket=srvSocket.accept(); … catch(IOException e) { System.out.println("Exception "+e.getMessage()); } } 18. Клиентский сокет в программе-клиенте Для подключения клиентских приложений к указанному адресу в Java используется класс Socket, экземпляр которого определяет в себе процессы подключения и передачи данных посредством сокетов. Для создания объекта Socket следует воспользоваться одним из конструкторов данного класса, например: Socket(InetAddress address, int port); где address – Internet-адрес компьютера, к которому осуществляется подключение, port –номер порта компьютера, к которому осуществляется подключение. 19. Фрагмент программыклиента import java.net.*; import java.io.*; public class MyClient { public static void main(String args[]) { Socket mySocket; String addr=“localhost"; int port=4; 20. Фрагмент программыклиента (продолжение) try { mySocket=new Socket(addr, port); … } catch(IOException e) { System.out.println("Exception "+e.getMessage()); } } } 21. Реализация чтения и записи После подключения через клиентский сокет можно выполнить процессы чтения и записи данных. Для этих целей в классе Socket имеются методы getInputStream() и getOutputStream(), которые открывают потоки ввода и вывода данных соответственно. 22. Использование потоков ввода и вывода Поток ввода DataInputStream input=new DataInputStream(mySocket.getInputStream()); String s=input.readLine(); Поток вывода PrintStream output=new PrintStream(mySocket.getOutputStream()); output.println("My Server response!"); Методы объекта Socket Помимо реализации процессов передачи данных через сетевые сокеты, в классе Socket объявлены методы, информирующие о процессах соединения и передачи данных: getInetAddress() –возвращает объект, определяющий адрес подключения; getPort() – возвращает порт, к которому осуществляется подключение; getLocalAddress() – возвращает адрес компьютера-клиента: getLocalPort() – возвращает порт компьютераклиента, через который выполняется данное соединение. Пример 1. MyServer.java MyClient.java Потоки Потоком называется независимая последовательность выполняемых действий Приведенный пример приложения содержит три потока: первый поток запускается методом main, два других запускаются методом start. Каждый из потоков выполняется параллельно. public class MyThread { public static void main(String args[]) { // объявить поток и выполнить для него метод start new MyT1().start(); // запуск первого потока new MyT2().start(); // запуск второго потока } } class MyT1 extends Thread // поток всегда является экземпляром класса Thread { public void run() // метод, выполняемый при запуске потока { System.out.println("Thread1"); } } class MyT2 extends Thread { public void run() { System.out.println("Thread2"); } } import java.net.*; // Пример 2. Сервер, работающий // последовательно import java.io.*; public class MyServer { int port=4; ServerSocket srvSocket; boolean flag=true; public MyServer() { try { srvSocket=new ServerSocket(port); System.out.println("My Server YES "); } catch(IOException e) { System.out.println("Error connection"+e.getMessage()); System.exit(0); } Socket clientSocket; while (flag) { if (srvSocket==null) return; try { clientSocket=srvSocket.accept(); DataInputStream input=new DataInputStream(clientSocket.getInputStream()); String s=input.readLine(); System.out.println(s); PrintStream output=new PrintStream(clientSocket.getOutputStream()); output.println("My Server response!"); output.println("Connect:"+new java.util.Date().toString()); s=input.readLine(); System.out.println("From Client:"+s); output.flush(); output.close(); clientSocket.close(); System.out.println("Client Connect:"+new java.util.Date().toString()); } catch(IOException e) { System.out.println("Exception "+e.getMessage()); } } } public static void main(String[] args) { MyServer msrv=new MyServer(); } } import java.net.*; // Пример 3. Сервер, работающий // параллельно import java.io.*; public class MyServer { int port=4; ServerSocket srvSocket; boolean flag=true; public class Session extends Thread { Socket clientSocket; public Session(Socket cSocket) { clientSocket=cSocket; } public void run() { try { DataInputStream input=new DataInputStream(clientSocket.getInputStream()); String s=input.readLine(); System.out.println(s); PrintStream output=new PrintStream(clientSocket.getOutputStream()); output.println("My Server response!"); output.println("Connect:"+new java.util.Date().toString()); s=input.readLine(); System.out.println("From Client:"+s); output.close(); clientSocket.close(); System.out.println("Client Connect:"+new java.util.Date().toString()); } catch(IOException e) { System.out.println("Exception "+e.getMessage()); } } } public MyServer() { try { srvSocket=new ServerSocket(port); System.out.println("My Server YES "); } catch(IOException e) { System.out.println("Error connection"+e.getMessage()); System.exit(0); } Socket clientSocket; while (flag) { if (srvSocket==null) return; try { clientSocket=srvSocket.accept(); Session ses=new Session(clientSocket); ses.start(); } catch(IOException e) { System.out.println("Exception "+e.getMessage()); } } } public static void main(String[] args) { MyServer msrv=new MyServer(); } } import java.net.*; // Пример 2. Клиент import java.io.*; public class MyClient { public static void main(String args[]) { System.out.println("Client running..."); Socket mySocket; String addr=""; String inStr=""; boolean flag=true; int port=4; if (args.length!=1) { addr="localhost"; } else addr=args[0]; while (flag) { try { mySocket=new Socket(addr, port); DataInputStream input=new DataInputStream(mySocket.getInputStream()); PrintStream output=new PrintStream(mySocket.getOutputStream()); output.println("Privet, Server!"); String s=input.readLine(); System.out.println("Answer1="+s); s=input.readLine(); System.out.println("Answer2="+s); System.out.println("Vvedite"); byte buffer[]=new byte[255]; //Чтение с клавиатуры int kol=System.in.read(buffer); inStr=new String(buffer); inStr=inStr.substring(0,kol-1); System.out.println(inStr); output.println(inStr); output.close(); input.close(); mySocket.close(); } catch(IOException e) { System.out.println("Exception "+e.getMessage()); } } } } while (flag) // фрагмент примера 3. Клиент { try { mySocket=new Socket(addr, port); DataInputStream input=new DataInputStream(mySocket.getInputStream()); DataInputStream input0=new DataInputStream(System.in); PrintStream output=new PrintStream(mySocket.getOutputStream()); output.println("Privet, Server!"); String s=input.readLine(); System.out.println("Answer1="+s); s=input.readLine(); System.out.println("Answer2="+s); System.out.println("Vvedite"); //ввод с клавиатуры inStr=input0.readLine(); System.out.println(inStr); output.println(inStr); output.close(); input.close(); mySocket.close(); } Пример преобразования типов в Java double f,f1; String s,s1; … f=12.34; s=String.valueOf(f); s1="2.4"; f1=Double.parseDouble(s1); f1=f1/f; s1=String.valueOf(f1); Пример проверки в Java if (s.equals("km")) System.out.println("kilometr"); else if (s.equals("cm")) System.out.println("santimetr"); else System.out.println("neverno");