Перейти к содержимому

Как сделать клиент серверное приложение java

  • автор:

Клиент-сервер на Java

Это первое приложение в односторонней связи. В случае односторонней связи клиент отправляет на сервер, но сервер не отправляет обратно клиенту. При двусторонней связи клиент отправляет на сервер, а сервер отправляет обратно клиенту.

Всего в приложении TCP / IP 4 варианта.

APPLICATION NUMBER FUNCTIONALITY
1st application Client to server communication (one-way)
2nd application Server to client communication (one-way)
3rd application Server sends file contents to client (two-way, non-continuous)
4th application Chat program (two-way, continuous)

1-е Приложение клиент-сервер

Приложение состоит из двух программ. Клиентская программа, работающая на стороне клиента, и серверная программа, работающая на стороне сервера. Клиентская программа WishesClient.java отправляет серверу наилучшие пожелания, а серверная программа WishesServer.java получает сообщение и печатает на своем терминале (мониторе).

Клиентская программа – WishesClient.java

import java.net.Socket; import java.io.OutputStream; import java.io.DataOutputStream; public class WishesClient < public static void main(String args[]) throws Exception < Socket sock = new Socket("127.0.0.1", 5000); String message1 = "Accept Best Wishes, Serverji"; OutputStream ostream = sock.getOutputStream(); DataOutputStream dos = new DataOutputStream(ostream); dos.writeBytes(message1); dos.close(); ostream.close(); sock.close(); >> Socket sock = new Socket ("127.0.0.1", 5000);

Конструктор класса Socket принимает два параметра – строку, IP-адрес сервера и целое число, номер порта на сервере, к которому клиент хотел бы подключиться. 127.0.0.1 – это адрес по умолчанию локальной системы в компьютерных сетях.

OutputStream ostream = sock.getOutputStream ();

Метод getOutputStream() класса Socket возвращает объект OutputStream, здесь объект является ostream. Это отправная точка всего общения (программы). Здесь сокет связан с потоками. Потоки способствуют передаче данных.

DataOutputStream dos = new DataOutputStream (ostream); dos.writeBytes (message1);

OutputStream является абстрактным классом; он не может быть использован напрямую. В приведенном выше коде он связан с конкретным классом DataOutputStream. Метод writeBytes() объекта DataOutputStream принимает строковое сообщение и передает его в Socket. Теперь клиентский сокет отправляется на другой сокет на сервере. Когда работа закончится, закройте потоки и сокет. Он освобождает дескрипторы (ссылки), связанные с системными ресурсами.

Ниже приведены исключения в вышеприведенной программе, создаваемые конструктором и различными методами.

  • Socket(“127.0.0.1”, 5000) выдает UnknownHostException
  • getOutputStream() генерирует IOException
  • writeBytes (message1) выдает IOException
  • Все методы close() выдают IOException
  • Серверная программа – WishesServer.java
import java.net.ServerSocket; import java.net.Socket; import java.io.InputStream; import java.io.DataInputStream; public class WishesServer < public static void main(String args[]) throws Exception < ServerSocket sersock = new ServerSocket(5000); System.out.println("server is ready"); // message to know the server is running Socket sock = sersock.accept(); InputStream istream = sock.getInputStream(); DataInputStream dstream = new DataInputStream(istream); String message2 = dstream.readLine(); System.out.println(message2); dstream .close(); istream.close(); sock.close(); sersock.close(); >>

ServerSocket sersock = новый ServerSocket (5000);

У сервера есть два задания: одно, как и ожидалось, должно связываться, а другое связывает соединение с номером порта 5000. Для связи он использует Socket, а для привязки – ServerSocket.

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

Socket sock = sersock.accept ();

accept() – это метод класса ServerSocket, используемый сервером для привязки соединения по номеру порта 5000, запрошенного клиентом.

InputStream istream = sock.getInputStream();

Метод getInputStream() объекта Socket возвращает объект InputStream, и это отправная точка серверной программы. Сервер использует входной поток при получении сообщения.

DataInputStream dstream = new DataInputStream (istream);

Поскольку InputStream является абстрактным классом, его нельзя использовать напрямую. Он связан с конкретным классом DataInputStream.

String message2 = dstream.readLine();

Метод readLine() объекта DataInputStream читает строку сообщения из сокета и возвращает ее. Это сообщение печатается на консоли.

Примечание. При компиляции этой программы вы получаете предупреждение из-за метода readLine() объекта DataInutStream; но программа выполняется. Чтобы избежать этого предупреждения, в следующей программе используется BufferedReader.

Выполнение клиентских и серверных программ

В одной системе, чтобы действовать как клиент и сервер, откройте два шDOS и обработайте одно как клиент, а другой – как сервер. Из одного приглашения DOS сначала запустите серверную программу, а из другого приглашения DOS запустите клиентскую программу. Вы получаете вывод при запросе сервера DOS.

Это приложение и следующее – только односторонняя связь, отправляющая или получающая. Но второй набор (после следующего) приложений является двусторонним, когда клиент и сервер могут отправлять и получать (оба). Для тестирования на выделенных серверах, можно обратиться сюда https://www.mixtelecom.ru/arenda-serverov.html

Для лучшего понимания вопрос-ответ из пакета java.lang.

Сколько существует типов внутренних классов?
Ответ: 4 типа.

Что такое файлы JAR?
Ответ: JAR-файл – это заархивированный файл, сжатый JVM.

Как преобразовать строку в форму типа данных?
Ответ: Преобразование строки в тип данных – байтовое, короткое, целое, длинное, плавающее, двойное, символьное и логическое.

Как преобразовать объект в строку?
Ответ: Объект в строку – toString()

Как сравнить два объекта?
Ответ: Сравнение объектов – hashCode() & equals()

Средняя оценка 3.1 / 5. Количество голосов: 16

Спасибо, помогите другим — напишите комментарий, добавьте информации к статье.

Или поделись статьей

Видим, что вы не нашли ответ на свой вопрос.

Помогите улучшить статью.

Напишите комментарий, что можно добавить к статье, какой информации не хватает.

Как написать простейшее клиент-серверное приложение?

Без применения дополнительных библиотек, основа низкоуровневого сетевого взаимодействия в Java строится на двух классах: Socket и ServerSocket .

Socket – клиентское подключение. Отправляет запросы и получает ответы с заданного порта/адреса по TCP/IP-соединению. Наследники могут реализовывать протоколы более высокого уровня сетевого стека, например SSLSocket . Похож на утилиту netcat из Unix-систем. Обслуживает одно подключение к серверу, обменивается данными через InputStream и OutputStream .

ServerSocket – сервер, приёмник подключений. Занимает на машине заданный свободный порт, и в одиночку принимает все подключения к нему. Опционально можно задать свой адрес, если текущая машина доступна по нескольким, а сокет должен быть доступен только по одному из них.

Ключевой метод серверного сокета – accept() . Вызов этого метода блокирует исполнение до тех пор, пока не придет новый запрос от клиента. Возвращает пришедший запрос в виде экземпляра класса Socket . Чтобы сделать сервер параллельным, accept() должен вызываться в параллельных потоках.

Стандартную внутреннюю реализацию сокетов можно подменить, установив для них статическую фабрику типа SocketImplFactory , методом setSocketFactory() .

Для высокоуровневых (HTTP, FTP) запросов в стандартной библиотеке есть класс URLConnection и его наследники.

Полный пример клиент-серверного приложения доступен в туториале на сайте Oracle.

Пример простого клиент-серверного приложения на Java

«Клиент-сервер» это очень распространенная и логичная архитектура приложений. Мне кажется, что в наши дни редко можно встретить standalone-клиентское приложение. Поэтому я принял решение рассмотреть пример построения клиент-серверного приложения на Java без привязки к конкретной задаче. Сначала вкратце пробежимся по классовой структуре приложения, потом посмотрим на отдельную реализацию каждого класса. В самом конце статьи я дам ссылку на скачивание архива с готовой структурой приложения. Итак, начнем.

Основные компоненты приложения

Основными компонентами, естественно, являются непосредственно клиент и сервер. Однако, кроме них необходим еще пакет вспомогательных классов, которые, в простейшем случае, будут отвечать за обмен сообщениями между клиентом и сервером. В минимальной комплектации нужны такие классы: MessageReader/MessageWriter(считывает/записывает сообщение в поток на сокете), MessageFactory(содержит идентификаторы всех возможных сообщений), набор сообщений-запросов(Request) и набор сообщений-ответов(Response). Все они будут размещены в пакете «core», который должны иметь у себя и клиент и сервер.

Рассмотрим классовую структуру всего проекта, а потом перейдем к реализации.

Классовая структура клиент-серверного приложения

- client (пакет файлов клиента) Client.java (логика клиента) ClientLauncher.java (запуск клиента) - core (вспомогательные классы) - communication (обмен сообщениями) MessageFactory.java (здесь хранятся все сообщения) MessageReader.java (чтение сообщений из потока) MessageWriter.java (запись сообщений в поток) - requests HandshakeRequest.java (запрос на обмен рукопожатиями) - responses HandshakeResponse.java (ответ на обмен рукопожатиями) IMessage.java (интерфейс для сообщения) Request.java (абстрактный класс "запрос") Response.java (абстрактный класс "ответ") - server (файлы сервера) ClientSession.java (сессия отдельного клиента - обработка запросов этого клиента) Context.java (контекст - общая информация сервера для всех клиентов) Server.java (логика сервера) ServerLauncher.java (запуск сервера) SessionsManager.java (хранит все текущие сессии)

Исходный код клиента на Java

Разобраться с клиентом гораздо проще, он по сути своей не делает ничего супер сложного, просто создает сокет и подключается к сервер-сокету с помощью связки host:port. Лаунчер создает объект класса Client и запускает его работу. Исходный код привожу без импортов, ибо любая IDE вам их подключит(те, кто пишет на Java точно знают, что без IDE очень сложно). Кроме того, в конце статьи вы сможете скачать архив с этим проектом.

ClientLauncher.java

public class ClientLauncher < public static void main(String[] args) < try < InetAddress host = InetAddress.getByName(args[0]); int port = Integer.parseInt(args[1]); //System.out.println(id); Client client = new Client(host, port); //Запускаем логику клиента client.start(); >catch (UnknownHostException e) < e.printStackTrace(); >> >

Client.java

public class Client < private final InetAddress host; private final int port; public Client(InetAddress host, int port) < this.host = host; this.port = port; >//Создает сокет, ридер райтер и запускает логику public void start() < //Создаем клиентский сокет try (Socket socket = new Socket(this.host, this.port)) < //Создаем ридер и райтер для обмена сообщениями MessageReader reader = new MessageReader(socket.getInputStream()); MessageWriter writer = new MessageWriter(socket.getOutputStream()); //Шлем серверу первое сообщение "рукопожатие" writer.writeRequest(new HandshakeRequest()); //Получаем ответ UniqueMessage msg = reader.readMessage(); //Проверяем, что это ответ на рукопожатие if(!(msg.message instanceof HandshakeResponse)) < return; >//Запуск логики приложения this.logicStart(); //socket.close(); > catch (IOException e) < e.printStackTrace(); >> public void logicStart() < //Логика приложения //. >>

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

Исходный код сервера на Java

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

Напомню, что в классе ClientSession описан основной алгоритм работы с клиентом, обмен сообщениями, данными и прочее. В классе Context содержится общая информация для всех клиентов сервера, например, пути для сохранения логов.

ServerLauncher.java

public class ServerLauncher < public static void main(String[] args) < Server server = new Server(); server.run(); >>

Server.java

public class Server implements Runnable < private final int port; private Context context; public Server() < this.port = 5000; this.context = new Context(); >@Override public void run() < try < ServerSocket ss = new ServerSocket(this.port); //Цикл ожидания подключений while(!this.context.stopFlag) < System.out.println("Waiting connection on port:" + this.port); //Момент ухода в ожидание подключения Socket clientSocket = ss.accept(); System.out.println("New client connected to server"); //Создается клиентская сессия ClientSession clientSession = new ClientSession(clientSocket, this.context); this.context.getSessionsManger().addSession(clientSession); //Запуск логики работы с клиентом clientSession.start(); >ss.close(); > catch (IOException e) < e.printStackTrace(); >> >

Context.java

//Данные, общие для всех клиентских сессий public class Context < private SessionsManager sessinonsManager; public boolean stopFlag; //Другие важные поля, которые должны знать все клиенты //. public Context() < this.stopFlag = false; this.sessinonsManager = new SessionsManager(); >public SessionsManager getSessionsManger() < return this.sessinonsManager; >>

ClientSession.java

//Основная логика клиента public class ClientSession extends Thread < private final Socket socket; private final MessageReader reader; private final MessageWriter writer; private final Context context; public ClientSession(final Socket socket, final Context context) throws IOException < this.socket = socket; this.reader = new MessageReader(socket.getInputStream()); this.writer = new MessageWriter(socket.getOutputStream()); this.context = context; >public void run() < UniqueMessage msg; try < msg = reader.readMessage(); //Рукопожатие if(msg.message instanceof HandshakeRequest) < if(((HandshakeRequest)msg.message).match()) < writer.writeResponse(new HandshakeResponse(), msg.uniqueId); >> //Обменялись рукопожатиями, начинаем работу this.doWork(); //выход this.socket.close(); > catch (IOException e) < e.printStackTrace(); >> private void doWork() <> >

SessionsManager.java

public class SessionsManager < private final Setsessions = new HashSet(); public SessionsManager() <> public synchronized void addSession(ClientSession session) < sessions.add(session); >public synchronized void removeSession(ClientSession session) < sessions.remove(session); >>

Вспомогательные классы из пакета «core»

Помещу все вспомогательные классы под один кат, название классов в точности соответствует названиям из списка «классовая структура» выше, по нему вы можете определить пакет каждого класса.

public class MessageFactory < //Идентификаторы запросов public static final int REQUEST_HANDSHAKE = 1; //Идентификаторы ответов private static final int RESPONSE_BASE = 0x40000000; public static final int RESPONSE_HANDSHAKE = RESPONSE_BASE + 1; //Ассоциативный массив: класс сообщения =>идентификатор сообщения private static final Map, Integer> idMap = new HashMap, Integer>(); static < idMap.put(HandshakeRequest.class, REQUEST_HANDSHAKE); idMap.put(HandshakeResponse.class, RESPONSE_HANDSHAKE); >private MessageFactory() < >//Создает сообщение по идентификатору public static IMessage createMessage(int messageId) throws IOException < if (messageId >RESPONSE_BASE) < switch (messageId) < case RESPONSE_HANDSHAKE: return new HandshakeResponse(); default: throw new IOException("Unknown message type " + messageId); >> else < switch (messageId) < case REQUEST_HANDSHAKE: return new HandshakeRequest(); default: throw new IOException("Unknown message type " + messageId); >> > public static int getMessageId(final IMessage message) < Integer return id.intValue(); >> public class MessageReader < //Длина заголовка сообщения public static final int HEADER_LENGTH = 12; private final DataInputStream dis; public MessageReader(InputStream is) < this.dis = new DataInputStream(is); >public UniqueMessage readMessage() throws IOException < //Читаем длину пакета из начала int packageLength = dis.readInt(); if (packageLength < HEADER_LENGTH) < throw new IOException("Wrong package length"); >//Считываем сообщение byte[] buf = new byte[packageLength — 4]; dis.readFully(buf); DataInputStream messageIS = new DataInputStream(new ByteArrayInputStream(buf)); int uniqueId = messageIS.readInt(); int message_id = messageIS.readInt(); IMessage message = MessageFactory.createMessage(message_id); message.readExternal(messageIS); System.out.println(«Message » + message.getClass().getName() + » received.»); return new UniqueMessage(message, uniqueId); > public static class UniqueMessage < public final IMessage message; public final int uniqueId; private UniqueMessage(IMessage message, int uniqueId) < this.message = message; this.uniqueId = uniqueId; >> > public class MessageWriter < private static final int INITIAL_BUFFER_SIZE = 128; private final DataOutputStream out; private Integer requestIdCounter = 0; public MessageWriter(OutputStream os) < this.out = new DataOutputStream(os); >private int getNewRequestId() < synchronized (requestIdCounter) < return ++requestIdCounter; >> private void writeMessage(final IMessage message, final int uniqueId) throws IOException < int messageId = MessageFactory.getMessageId(message); ByteArrayOutputStream baos = new ByteArrayOutputStream( INITIAL_BUFFER_SIZE); message.writeExternal(new DataOutputStream(baos)); int messageLength = baos.size() + MessageReader.HEADER_LENGTH; synchronized (out) < out.writeInt(messageLength); out.writeInt(uniqueId); out.writeInt(messageId); baos.writeTo(out); out.flush(); >System.out.println(«Message » + message.getClass().getName() + » sent.»); > public int writeRequest(final Request request) throws IOException < int uniqueId = getNewRequestId(); writeMessage(request, uniqueId); return uniqueId; >public void writeResponse(final Response response, int requestId) throws IOException < writeMessage(response, requestId); >> public class HandshakeRequest extends Request < public static final String HANDSHAKE_STRING = "handshake request"; private String handshake; @Override public void readExternal(DataInputStream dis) throws IOException < handshake = dis.readUTF(); >@Override public void writeExternal(DataOutputStream dos) throws IOException < dos.writeUTF(HANDSHAKE_STRING); >public boolean match() < return HANDSHAKE_STRING.equals(handshake); >> public class HandshakeResponse extends Response < public static final String HANDSHAKE_RESPONSE_STRING = "handshake response"; private String handshake; @Override public void readExternal(DataInputStream dis) throws IOException < handshake = dis.readUTF(); >@Override public void writeExternal(DataOutputStream dos) throws IOException < dos.writeUTF(HANDSHAKE_RESPONSE_STRING); >public boolean match() < return HANDSHAKE_RESPONSE_STRING.equals(handshake); >> public interface IMessage < public void writeExternal(DataOutputStream dos) throws IOException; public void readExternal(DataInputStream dis) throws IOException; >public abstract class Request implements IMessage < >public abstract class Response implements IMessage

Пара слов о сообщениях, классы Request и Response являются абстрактными и играют роль классификаторов сообщения. Благодаря этому очень удобно разграничивать «запросы» от «ответов». В этом примере я привел только одно сообщение — Handshake, которое отвечает за первое «рукопожатие» клиента и сервера. Все последующие сообщения должны быть прописаны в классе MessageFactory по примеру этих двух.

Скачать архив с шаблоном клиент-серверного приложения на Java

Заключение

Главная цель, которую я преследовал при написании этой статьи заключается в том, чтобы дать возможность мне или кому-либо еще за считанные минуты «собрать» готовое клиент-серверное приложение. Кажется, я с этим справился, если будут дополнения или замечания, пишите в комментариях или на почту. А на сегодня у меня все, спасибо за внимание!

Пример приложения клиент/сервер на языке Java

С помощью следующего приложения мы осветим вопросы программирования сокетов как для протокола TCP, так и для протокола UDP. Приложение функционирует следующим образом.

1. Клиент считывает со стандартного устройства ввода (клавиатуры) строку символов и посылает эту строку серверу через свой сокет.
2. Сервер принимает строку через свой сокет.
3. Сервер переводит все символы строки в верхний регистр.
4. Сервер отсылает модифицированную строку клиенту.
5. Клиент получает строку и печатает ее с помощью стандартного устройства вывода (монитора).

Мы начнем с рассмотрения приложения, в котором взаимодействие клиента и сервера осуществляется через логическое соединение по протоколу TCP (рис. 2.20).

220.png

Ниже мы приведем тексты программ для клиентской и серверной сторон приложения и снабдим пояснениями каждую строку кода. Программа-клиент названа TCPClient.java, программа-сервер — TCPServer.java. Отметим, что приведенные программы лишь иллюстрируют ключевые фрагменты приложения и не претендуют на то, чтобы называться «хорошими» с точки зрения практического применения. Для улучшения программ приведенные тексты следовало бы снабдить несколькими дополнительными строками.

После компиляции обеих программ (каждой на своем компьютере) первой запускается программа-сервер, поскольку для установления соединения серверный процесс должен ожидать запроса со стороны клиентского процесса. Клиентский процесс создается после запуска программы-клиента, и в его функцию входит инициирование TCP-соединения с сервером. После того как соединение установлено, пользователь, находящийся на клиентской стороне, может вводить строки символов и получать их обратно в верхнем регистре.

Ниже приведен текст программы TCPClient.java.

import java.io.*;
import java.net.*;
class TCPClient public static void main(String argv[]) throws Exception
String sentence;
String modifiedSentence;
BufferedReader inFromUser =
new BufferedReader(
new InputStreamReader(System.in));
Socket clientSocket = new Socket (“hostname”. 6789);
DataOutputStream outToServer =
new DataOutputStream(
clientSocket.getOutputStream());
BufferedReader inFromServer =
new BufferedReader(
new InputStreamReader(
cli entSoket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + ‘\n’);
modifiedSentence = inFromServer.readLine();
System.out.printing “FROM SERVER: ” + modifiedSentence);
clientSocket.close();
>
>

Как показано на рис. 2.21, программа TCPClient создает три потока данных и один сокет.
Сокет имеет название clientSocket. Поток inFromUser является входным потоком данных программы и связан со стандартным устройством ввода (клавиатурой). Все символы, вводимые с клавиатуры пользователем, попадают в поток inFromUser. Другой входной поток данных программы, inFromServer, связан с сокетом и состоит из символов, передаваемых серверной стороной приложения. Выходной поток данных программы TCPClient имеет название outToServer и также связан с сокетом. Этот поток содержит символы, передающиеся серверу для обработки.

Теперь рассмотрим приведенный код подробнее. Первые две строки содержат имена
двух Java-пакетов, java i’о и java. net:

Пакет java.io содержит классы входных и выходных потоков данных. Обычно этими классами являются BufferedReader и DataOutputStream, которые и были использованы в программе. Пакет java.net хранит классы, поддерживающие работу с компьютерной сетью (Socket и ServerSocket). Объект clientSocket программы порожден классом Socket.

class TCPClient public static void main(String argv[]) throws Exception

>

221.png

Конструкции, аналогичные приведенной выше, являются стандартными в практике программирования на Java. Первая строка представляет собой начало блока определения класса. В ней присутствует ключевое слово class и имя определяемого класса TCPClient. Класс может содержать переменные и методы; в объявлении класса они заключены в фигурные скобки и фактически составляют блок определения класса. В классе TCPClient нет переменных, он содержит единственный метод с именем main(). Методы похожи на процедуры и функции языков, подобных С; метод main() также играет роль, схожую с функцией main() в С или С++. Когда интерпретатор Java исполняет приложение (будучи вызванным управляющим классом приложения), он обращается к методу main() этого класса. Метод mainQ вызывает все остальные методы, используемые в приложении. Если в данный момент вы впервые сталкиваетесь с Java-приложением, можете не обращать внимания на ключевые слова public, static, void, main и throws Exception.

String sentence;
String modifiedSentence;

Приведенные две строки являются объявлениями объектов типа String. Объект sentence предназначен для хранения строки, вводимой пользователем и передаваемой серверу. Объект modifiedSentence содержит строку, принимаемую от сервера и выводимую на стандартное устройство вывода.

BufferedReader inFromUser =
new BufferedReader(new InputStreamReaderCSystem.in));

Здесь происходит создание потокового объекта in From User типа BufferedReader. Инициализация потока данных производится объектом System.in, связывающим поток со стандартным устройством ввода. После выполнения этой команды клиенту начинают передаваться символы, вводимые пользователем с клавиатуры.

Socket clientSocket = new Socket (“hostname”, 6789);

В приведенной строке происходит создание объекта clientSocket типа Socket. Кроме того, при этом инициируется TCP-соединение между клиентом и сервером. Слово hostname необходимо заменить именем хоста, сохранив кавычки (например, “_fling.seas.upenn.edu”). Перед началом установки TCP-соединения клиент производит DNS-запрос IP-адреса хоста. Значение 6789 — это номер порта; вы можете выбрать другое число, однако необходимо помнить, что клиентская и серверная стороны должны использовать один и тот же номер порта. Как упоминалось ранее, IP-адрес хоста в совокупности с номером порта приложения идентифицирует серверный процесс.

DataOutputStream outToServer =
new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer =
new BufferedReader(new InputStreamReader(clientSoket.getlnputstream()));

Здесь происходит создание потоковых объектов, связанных с сокетом. Поток outToServer обеспечивает вывод программы через сокет, а поток inFromServer предназначен для приема данных от серверной стороны (см. рис. 2.21).

Эта строка помещает последовательность символов, вводимых пользователем, в переменную sentence. Ввод оканчивается нажатием пользователем клавиши Enter. Как видим, для помещения символов в переменную используется потоковый объект inFromUser.

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

modifiedSentence = inFromServer. readLineO;

Ответ сервера принимается во входной поток inFromServer, откуда принятая строка копируется в переменную modifiedSentence. Помещение символов в строку modifiedSentence продолжается до тех пор, пока не будет получен символ возврата каретки.

System.out.println(“FROM SERVER: ” + modifiedSentence);

Здесь происходит вывод принятой от сервера строки на монитор,

Эта строка закрывает сокет, а следовательно, и TCP-соединение между клиентом и сервером. Как будет показано в главе 3, исполнение этой команды ведет к отправке TCP-клиентом сообщения ТСР-серверу.

Ниже приведен текст программы TCPServer.java.

import java.io.*;
import java.net.*;
class TCPServer public static void main(String argv[]) throws Exception
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket (6789);
while (true) Socket connectionSocket = welcomeSocket.
accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReaderC
connectionSocket.getInputStream()));
DataOutputStream outToClient =
New DataOutputStreamC connectionSocket.getOutputStream());
clientSentence = inFromClient. readLineO; capitalizedSentence =
clientSentence.toUpperCaseO + ‘\n’;
outToClient.writeBytes(capitalizedSentence);
>
>
>

Программа TCPServer имеет много общего с программой TCPClient; рассмотрим ее подробнее, опустив строки, общие с программой TCPClient и описанные выше.

ServerSocket welcomeSocket = new ServerSocket (6789);

Здесь происходит создание объекта welcomeSocket типа ServerSocket. Объект welcomeSocket представляет собой впускающий сокет, с помощью которого клиент устанавливает первоначальный контакт с сервером. Для этого сокета используется порт с номером 6789, совпадающим с номером порта сокета клиента (мы раскроем причины совпадения номеров портов сокетов клиента и сервера в главе 3). Протокол TCP устанавливает прямой виртуальный канал между сокетом clientSocket на клиентской стороне и connectionSocket на серверной стороне, после чего клиент и сервер могут свободно осуществлять обмен информацией. После создания сокета connectionSocket сервер может вновь использовать сокет welcomeSocket для инициирования других соединений с клиентами (приведенная программа не обрабатывает новых соединений, однако ее можно модифицировать соответствующим образом).

Далее программа создает несколько потоковых объектов, аналогичных clientSocket.

capitalizedSentence = clientSentence.toUpperCaseO + ‘\n’;

та команда основная в приложении. Она выполняет получение строки, передаваемой клиентом, перевод строки в верхний регистр с помощью метода tollpperCase() и добавление в конец символа возврата каретки. Все остальные команды программы являются периферийными и не касаются взаимодействия сервера с клиентом.

Для того чтобы протестировать совместную работу наших программ, следует поместить их на разные хосты и указать в программе TCPClient имя хоста-сервера. Затем необходимо запустить программу TCPServer, чтобы создать серверный процесс. Серверный процесс будет находиться в состоянии ожидания до тех пор, пока клиентский процесс не инициирует TCP-соединение; для этого, в свою очередь, нужно запустить программу TCPClient. Наконец, чтобы проверить наше приложение в действии, следует ввести на стороне клиента строку, оканчивающуюся символом возврата каретки (он вводится нажатием клавиши Enter).

Используя приведенные тексты программ, вы можете создать собственное приложение клиент/сервер. Например, вы можете изменить работу сервера таким образом, что вместо перевода строки в верхний регистр он будет подсчитывать количество букв «s» в ней.

  • Метки: http, ip, tcp, udp, протокол, сеть
  • Программирование ТСР-сокетов

Уточнения, корректировки и обсуждения статьи «Пример приложения клиент/сервер на языке Java» — под данным текстом, в комментариях.

Ответственность, за все изменения, внесённые в систему по советам данной статьи, Вы берёте на себя.

Копирование статьи «Пример приложения клиент/сервер на языке Java», без указания ссылки на сайт первоисточника Компьютерные сети и многоуровневая архитектура интернета (conlex.kz), строго запрещено.

Кстати, фильм 2016 года Инферно через торрент 720 hd качество можно скачать на rosreetr.ru

9 Комментариев для “ Пример приложения клиент/сервер на языке Java ”

ни подскажите , откудо я могу найти литературу про client-server opplication .

Толку от этой статьи, если с ней разберется только тот, кто понимает, что символ C надо заменить на открывающую скобку, и почему надо поменять одни кавычки на другие кавычки…

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

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