Пример 7.1. Примитивный клиент



import java.net.Socket;

 

class Client{

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

// Имя хоста и номер порта

String host = "localhost";

int port = 3333;

// Протокол передачи

// Запрос (3 целых чила): [операция][аргумент 1][аргумент 2]

// Ответ (1 целое число): [результат]

// Операции: 0 - сложение, 1 - умножение

int operation = 1;

int arg1 = 5;          int arg2 = 2;

try {

   System.out.println("Client is running");

// запрос клиента на соединение

   Socket sock = new Socket(host, port);

   // Исходящий поток

   DataOutputStream outStream = new DataOutputStream(

                                    sock.getOutputStream());

  // Отправляем запрос и аргументы

   outStream.writeInt(operation);

   outStream.writeInt(arg1);

   outStream.writeInt(arg2);

   // Входящий поток

   DataInputStream inStream = new DataInputStream(

                                  sock.getInputStream());

   int d = inStream.readInt();

   System.out.println("Result is " + d); 

   // Завершаем потоки и закрываем сокет

   inStream.close();   outStream.close(); sock.close(); 

}

catch(Exception e)    { System.err.println(e); } 

}

 

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

Для создания серверного сокета в пакете java.net есть класс ServerSocket. В конструкторе этого класса указывается номер порта ServerSocket(int port).Основной метод этого класса accept() ожидает поступления запроса. Когда запрос получен, метод устанавливает соединение с клиентом и возвращает объект класса socket, через который сервер будет обмениваться информацией с клиентом. Обратите внимание, что для каждого клиента сервер создает свой поток, в котором происходит их взаимодействие.


    Примитивный сервер

class Server {

public static void main(String[] args){

try {

   System.out.println("Server is running");

   int port = 3333;

    // создание серверного сокета

   ServerSocket ss = new ServerSocket(port);

   // Ждет клиентов и для каждого создает отдельный поток

   while (true)    {

       Socket s = ss.accept();

       ServerConnectionProcessor p =

                                 new ServerConnectionProcessor(s);

       p.start();

   }

}

catch(Exception e) { System.out.println(e); } 

}

}

 

class ServerConnectionProcessor extends Thread { 

private Socket sock;

public ServerConnectionProcessor(Socket s) { 

   sock = s;

}

public void run() {

   try   {

       // Получает запрос

       DataInputStream inStream = new DataInputStream(

                                      sock.getInputStream());

       int operationId = inStream.readInt();

       int arg1 = inStream.readInt();

       int arg2 = inStream.readInt();

       // Выполняет расчет

       int result = 0;

       if (operationId == 0)       { result = arg1 + arg2; }

       else if (operationId == 1) { result = arg1 * arg2; }

       // Отправляет ответ

       DataOutputStream outStream = new DataOutputStream(

                                        sock.getOutputStream());

       outStream.writeInt(result);

       // Подождем немного и завершим поток

       sleep(1000);

       inStream.close(); outStream.close(); sock.close(); 

   }

   catch(Exception e) { System.out.println(e); } 

}

 

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

 

Работа по протоколу UDP

 

Для посылки дейтаграмм отправитель и получатель создают сокеты дейтаграммного типа. В Java их представляет класс DatagramSocket. В классе три конструктора:

DatagramSocket() — создаваемый сокет присоединяется к любому свободному порту на локальной машине;

DatagramSocket(int port) — создаваемый сокет присоединяется к порту port на локальной машине;

DatagramSocket(int port, InetAddress addr) — создаваемый сокет присоединяется к порту port; аргумент addr — один из адресов локальной машины.

Класс содержит массу методов доступа к параметрам сокета и, кроме того, методы отправки и приема дейтаграмм:

send(DatagramPacket pack) — отправляет дейтаграмму, упакованную в пакет pack;

receive (DatagramPacket pack) — дожидается получения дейтаграммы и заносит ее в пакет pack.

При обмене дейтаграммами соединение обычно не устанавливается, дейтаграммы посылаются наудачу, в расчете на то, что получатель ожидает их.

При посылке дейтаграммы по протоколу UDP сначала создается сообщение в виде массива байтов, например,

String mes = "This is the sending message.";

byte[] data = mes.getBytes();

Потом записывается адрес — объект класса inetAddress:

InetAddress addr = InetAddress.getByName (host);

Затем сообщение упаковывается в пакет — объект класса DatagramPacket. При этом указывается массив данных, его длина, адрес и номер порта:

DatagramPacket pack = new DatagramPacket(data, data.length, addr, port);

Далее создается дейтаграммный сокет и дейтаграмма отправляется

DatagramSocket ds = new DatagramSocket();

ds.send(pack);

После посылки всех дейтаграмм сокет закрывается, не дожидаясь какой-либо реакции со стороны получателя:

ds.close ();

 Прием и распаковка дейтаграмм производится в обратном порядке, вместо метода send() применяется метод receive (DatagramPacket pack).

В примере 7.2 представлен класс, посылающий сообщения на localhost, порт номер 3333. Класс, описанный в примере 4, принимает эти сообщения и выводит их в свой стандартный вывод.

 


Дата добавления: 2018-04-15; просмотров: 287; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!