Spec-Zone .ru
спецификации, руководства, описания, API
След: Пользовательские Сети
Урок: Все О Сокетах
Запись Стороны сервера Сокета
Домашняя страница > Пользовательские Сети > Все О Сокетах

Запись Стороны сервера Сокета

Этот раздел показывает Вам, как записать сервер и клиент, который идет с ним. Сервер в клиент-серверной паре подает Удар шутки Удара. Удар шутки Удара одобряются дочерними элементами и обычно являются механизмами для плохой игры слов. Они идут как это:

Сервер: "Удар удар!"
Клиент: "Кто там?"
Сервер: "Правый".
Клиент: "Правый, кто?"
Сервер: "Правые залы с ветвями падуба."
Клиент: "Стон".

Пример состоит из двух независимо рабочих программ Java: клиентская программа и программа сервера. Клиентская программа реализуется единственным class, KnockKnockClient, и очень подобно EchoClient пример от предыдущего раздела. Программа сервера реализуется двумя классами: KnockKnockServer и KnockKnockProtocol, KnockKnockServer содержит main метод для программы сервера и выполняет работу слушания порта, установления соединений, и чтения из и записи в сокет. KnockKnockProtocol подает шутки. Это отслеживает текущую шутку, текущее состояние (отправленный удар удар, отправленный подсказку, и так далее), и возвращает различные текстовые части шутки в зависимости от текущего состояния. Этот объект реализует протокол - язык, который клиент и сервер согласился использовать, чтобы связаться.

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

Удар Сервер Удара

Этот раздел идет через код, который реализует Удар программа сервера Удара. Вот полный источник для KnockKnockServer class.

Программа сервера начинается, создавая новое ServerSocket объект слушать на определенном порту (см. оператор полужирным в следующем сегменте кода). При записи сервера выберите порт, который уже не выделяется некоторой другой службе. KnockKnockServer слушает на порту 4444, потому что 4, оказывается, мое любимое число, и порт 4444 не используется ни для чего больше в моей среде:

try {
    serverSocket = new ServerSocket(4444);
} 
catch (IOException e) {
    System.out.println("Could not listen on port: 4444");
    System.exit(-1);
}

ServerSocket a java.net class, который обеспечивает системно-независимую реализацию стороны сервера клиент-серверного сокетного соединения. Конструктор для ServerSocket выдает исключение, если оно не может слушать на указанном порту (например, порт уже используется). В этом случае, KnockKnockServer не имеет никакого выбора, кроме как выходить.

Если сервер успешно связывает с его портом, то ServerSocket объект успешно создается, и сервер продолжается к следующему шагу - принятие соединения от клиента (показанный полужирным):

Socket clientSocket = null;
try {
    clientSocket = serverSocket.accept();
} 
catch (IOException e) {
    System.out.println("Accept failed: 4444");
    System.exit(-1);
}

accept метод ожидает, пока клиент не запускает и запрашивает соединение на узле и порту этого сервера (в этом примере, сервер работает на гипотетической машине taranis на порту 4444). Когда соединение требуют и успешно устанавливается, принять метод возвращает новое Socket объект, который связывается с тем же самым локальным портом и имеет его удаленный адрес и удаленный набор порта тому из клиента. Сервер может связаться с клиентом по этому новому Socket и продолжайте прислушиваться к клиентским запросам соединения на оригинале ServerSocket Эта определенная версия программы не прислушивается к большему количеству клиентских запросов соединения. Однако, измененная версия программы обеспечивается в Поддержке Многократных Клиентов.

После того, как сервер успешно устанавливает соединение с клиентом, он связывается с клиентом, использующим этот код:

PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = 
    new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;

// initiate conversation with client
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);

while ((inputLine = in.readLine()) != null) {   
    outputLine = kkp.processInput(inputLine);
    out.println(outputLine);
    if (outputLine.equals("Bye."))
    break;
}

Этот код:

  1. Получает поток ввода и вывода сокета и открывает читателей и писателей на них.
  2. Передача новичков с клиентом при записи в сокет (показанный полужирным).
  3. Связывается с клиентом, читая из и при записи в сокет ( while цикл).

Шаг 1 уже знаком. Шаг 2 показывают полужирным и стоит нескольких комментариев. Полужирные операторы в сегменте кода выше инициируют разговор с клиентом. Код создает a KnockKnockProtocol объект - объект, который отслеживает текущую шутку, текущее состояние в пределах шутки, и так далее.

После KnockKnockProtocol создается, вызовы кода KnockKnockProtocol's processInput метод, чтобы получить первое сообщение, что сервер передается клиенту. Для этого примера первой вещью, которую говорит сервер, является "Удар! Стучите!" Затем, сервер пишет информацию в PrintWriter соединенный с клиентским сокетом, таким образом отправляя сообщение клиенту.

Шаг 3 кодируется в while цикл. Пока клиент и сервер все еще имеют что-то, чтобы сказать друг другу, чтениям сервера от, и пишет в сокет, отправляя сообщения назад и вперед между клиентом и сервером.

Сервер, инициируемый разговор с "Ударом! Стучите!" таким образом, впоследствии сервер должен ожидать клиента, чтобы сказать, "Кто там?" В результате цикл с условием продолжения выполняет итерации на чтении от входного потока. readLine метод ожидает, пока клиент не отвечает при записи чего-то в его поток вывода (входной поток сервера). Когда клиент отвечает, сервер передает ответ клиента на KnockKnockProtocol возразите и спрашивает KnockKnockProtocol объект для подходящего ответа. Сервер сразу отправляет ответ клиенту через поток вывода, соединенный с сокетом, используя звонок println. Если ответ сервера, сгенерированный от KnockKnockServer объект "До свидания". это указывает, что клиент больше не хочет шутки и выходы цикла.

KnockKnockServer class является сервером хорошего поведения, таким образом, последние несколько строк этого раздела KnockKnockServer очистите, закрывая все потоки ввода и вывода, клиентский сокет, и сокет сервера:

out.close();
in.close();
clientSocket.close();
serverSocket.close();

Удар Протокол Удара

KnockKnockProtocol class реализует протокол что использование клиента и сервера, чтобы связаться. Этот class отслеживает то, где клиент и сервер находятся в их разговоре, и подает ответ сервера на операторы клиента. KnockKnockServer объект содержит текст всех шуток и удостоверяется, что клиент дает надлежащий ответ на операторы сервера. Это не сделало бы, чтобы сделать, чтобы клиент сказал "Правый кто?" когда сервер говорит "Удар! Стучите!"

У всех клиент-серверных пар должен быть некоторый протокол, которым они говорят друг с другом; иначе, данные, которые передают назад и вперед, были бы бессмысленны. Протокол, что Ваше собственное использование клиентов и серверов зависит полностью от передачи, требуемой ими выполнить задачу.

Удар Клиент Удара

KnockKnockClient class реализует клиентскую программу, которая говорит с KnockKnockServer. KnockKnockClient основано на EchoClient программа в предыдущем разделе, Читающем из и Пишущем в Сокет и, должна быть несколько знакомой Вам. Но мы будем пробегаться через программу так или иначе и смотреть на то, что происходит в клиенте в контексте того, что продолжается в сервере.

Когда Вы запускаете клиентскую программу, сервер должен уже работать и слушать порт, ожидая клиента, чтобы запросить соединение. Так, первая вещь, которую делает клиентская программа, состоит в том, чтобы открыть сокет, который соединяется с сервером, работающим на имени узла и определенном порту:

kkSocket = new Socket("taranis", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));

Создавая его сокет, KnockKnockClient использует имя хоста taranis, имя гипотетической машины на нашей сети. Когда Вы вводите и выполняете эту программу, изменяете имя хоста на имя машины на Вашей сети. Это - машина, на которой Вы будете работать KnockKnockServer.

KnockKnockClient программа также определяет номер порта 4444, создавая его сокет. Это - удаленный номер порта - число порта на машине сервера - и является портом к который KnockKnockServer слушает. Сокет клиента связывается с любым доступным локальным портом - порт на клиентской машине. Помните, что сервер получает новый сокет также. Тот сокет связывается с локальным номером порта 4444 на его машине. Сокет сервера и сокет клиента соединяются.

Затем прибывает цикл с условием продолжения, который реализует передачу между клиентом и сервером. Сервер говорит сначала, таким образом, клиент должен слушать сначала. Клиент делает это, читая из входного потока, присоединенного к сокету. Если сервер действительно говорит, он говорит "До свидания". и клиент выходит из цикла. Иначе, клиент выводит на экран текст к стандартному выводу и затем читает ответ от пользователя, который вводит в стандартный ввод. После того, как пользователь вводит возврат каретки, клиент отправляет текст серверу через поток вывода, присоединенный к сокету.

while ((fromServer = in.readLine()) != null) {
    System.out.println("Server: " + fromServer);
    if (fromServer.equals("Bye."))
        break;

    fromUser = stdIn.readLine();
    if (fromUser != null) {
        System.out.println("Client: " + fromUser);
        out.println(fromUser);
    }
}

Передача заканчивается, когда сервер спрашивает, хочет ли клиент услышать другую шутку, клиент говорит не, и сервер говорит "До свидания".

В интересах хорошего обслуживания клиент закрывает его потоки ввода и вывода и сокет:

out.close();
in.close();
stdIn.close();
kkSocket.close();

Выполнение Программ

Следует запустить программу сервера сначала. Чтобы сделать это, выполните программу сервера, используя интерпретатор Java, так же, как Вы были бы любое другое приложение Java. Не забудьте выполнять сервер на машине, которую определяет клиентская программа, когда это создает сокет.

Затем, выполните клиентскую программу. Отметьте, что можно выполнить клиент на любой машине на Вашей сети; это не должно работать на той же самой машине как сервер.

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

Если Вы забываете изменять имя хоста в исходном коде для KnockKnockClient программа, Вы будете видеть следующее сообщение об ошибке:

Don't know about host: taranis

Чтобы фиксировать это, измените KnockKnockClient программа и обеспечивает допустимое имя хоста для Вашей сети. Перекомпилируйте клиентскую программу и попробуйте еще раз.

Если Вы пытаетесь запустить второй клиент, в то время как первый клиент соединяется с сервером, второй клиент только зависает. Следующий раздел, Поддерживая Многократные Клиенты, говорит о поддержке многократных клиентов.

Когда Вы успешно получите соединение между клиентом и сервером, Вы будете видеть следующий текст, выведенный на экран на Вашем экране:

Server: Knock! Knock!

Теперь, следует ответить:

Who's there?

Клиент повторяет то, что Вы вводите, и отправляет текст серверу. Сервер отвечает первой строкой одного из многого Удара шутки Удара в его репертуаре. Теперь Ваш экран должен содержать это (текст, который Вы вводили, полужирным):

Server: Knock! Knock!
Who's there?
Client: Who's there?
Server: Turnip

Теперь, Вы отвечаете:

Turnip who?"

Снова, клиентское эхо, что Вы вводите и отправляете тексту серверу. Сервер отвечает изюминкой. Теперь Ваш экран должен содержать это:

Server: Knock! Knock!
Who's there?
Client: Who's there?
Server: Turnip
Turnip who?
Client: Turnip who?
Server: Turnip the heat, it's cold in here! Want another? (y/n)   

Если Вы хотите услышать другую шутку, тип y; в противном случае тип n. Если Вы тип y, сервер начинается снова с "Удара! Стучите!" Если Вы тип n, сервер говорит "До свидания". таким образом вызывая и клиент и сервер, чтобы выйти.

Если в какой-либо точке Вы делаете ошибку ввода, KnockKnockServer возразите ловит это, и сервер отвечает сообщением, подобным этому:

Server: You're supposed to say "Who's there?"!

Сервер тогда запускает шутку снова:

Server: Try again. Knock! Knock!

Отметьте что KnockKnockProtocol объект следит за написанием и пунктуацией, но не о написании прописными буквами.

Поддержка Многократных Клиентов

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

Основной поток логики в таком сервере - это:

while (true) {
    accept a connection;
    create a thread to deal with the client;
}

Поток читает из и пишет в клиентское соединение по мере необходимости.


Попробуйте Это: 

Измените KnockKnockServer так, чтобы это могло обслужить многократные клиенты одновременно. Два класса составляют наше решение: KKMultiServer и KKMultiServerThread. KKMultiServer циклы навсегда, прислушиваясь к клиентским запросам соединения на a ServerSocket. Когда запрос входит, KKMultiServer принимает соединение, создает новое KKMultiServerThread возразите, чтобы обработать это, руки это, сокет, возвращенный из, принимает, и запускает поток. Затем сервер возвращается к прислушиванию к запросам соединения. KKMultiServerThread объект связывается с клиентом, читая из и при записи в сокет. Выполните новый Удар сервер Удара и затем выполните несколько клиентов по очереди.



Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Чтение из и Запись в Сокет
Следующая страница: Все О Дейтаграммах