Пример 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; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!