Проста клієнт-серверна муть на сокетах 3


На курсах IT Академії вчора видали завдання склепати програмку, яка б складалася із серверної та клієнтської частин. Сервер чекає на коннект з боку клієнта і відсилає йому поточний час, а клієнт цей час виводить собі кудись в консоль.

Серйозно я цим поки не займався, а просто наклепав дві сторінки сорців у жанрі бидлокоду, від яких, сподіваюся, у тічерів IT Академії волосся стане дибом 🙂 Якщо робити культурно, то треба прикручувати Thread – тоді можна буде хоч затримку зробити, бо у такому вигляді виходить якийсь сокетний флудер. Людям вразливим (а також вагітним, жінкам, дітям) далі не читати.

Першим ділом робимо сервер. Лістинг нижче:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Server {
public static void main(String[] ar) throws IOException{
int port = 3664;

DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
ServerSocket ss = new ServerSocket(port);
System.out.println("Waiting for a client...");

Socket socket = ss.accept();
System.out.println("Client Connected");
// Getting I/O streams
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
// Converting streams to data I/O
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);

String line = null;//Request String
while (true) {
line = in.readUTF().toString();//Get request text
System.out.println("Got request : " + line);
System.out.println("sending time");
Date date = new Date();
String timeline = dateFormat.format(date);
out.writeUTF(timeline);//Send time
out.flush();
System.out.println("Waiting for the next request...");
}

}
}

Оу, форматування попсувалося. Так навіть краще 😉 Кілька коментарів у коді є, але ще невеличке пояснення. У першому куску просто імпорти. Далі – створюємо клас Server, який і буде, власне, сервером. Оскільки це бидлокодинг, то пишемо, що єдиний метод даного класу (main) просто throws IOException і забиваємо. Зате придумуємо “трушний” порт 3664.

Рядочок DateFormat dateFormat = new SimpleDateFormat(“HH:mm:ss”); дозволяє нам задати формат відображення системної дати\часу. Оскільки нам треба суто час, то і видавати будемо у вигляді години:хвилини:секунди. Далі створюємо серверний сокеі і сідаємо чекати стуку від клієнта.

Коли клієнт таки до нашого сервера достукається, то треба із ним скомунікуватися якось. Для цього отримуємо вхідний і вихідний потоки (відповідно sin та sout). Проблема у тому, що ці потоки передають дані байтами, а особисто я байти не вмію читати і хотів би приймати і передавати текстом. Тому далі на базі наших потоків треба створити такі, які розуміють більш складні констукції. Це DataInputStream і DataOutputStream.

Лишився останній шматок коду: власне прийом запиту і передача часу. Все це робиться у “вічному” циклі while (true). Тут ніби нюансів нема особливих, хіба що варто було б не просто вивести текст запиту в консоль, але і перевірити його на рівність якійсь конкретній величині (аби не розказувати поточний час випадковим клієнтам, які постукали у цей порт, а лише тому, хто свідомо за цим часом прийшов). Потім, зараз ще клієнт писати.

І, ясне діло, при відключенні клієнта весь цей сервер навернеться через несподіваний розрив з’єднання. Як мінімум треба скористатися конструкцією try-catch-finally і закрити сокет у будь-якому випадку. Потім…

Переходимо до лістингу клієнта, цього разу пропускаємо пачку імпортів, бо вона десь така сама, як і у сервера.

public class Client {
public static void main(String[] ar) throws UnknownHostException, IOException {
int serverPort = 3664; // True port number (36+64=100 :))

Socket socket = new Socket("localhost", serverPort);
System.out.println("Connected to server");
// Getting I/O Streams
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
// Converting streams to data I/O
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);

while (true) {
String line = "WhatTimeISItNow";//Simple request text (not used yet)
out.writeUTF(line); // Sending request
out.flush(); // flush buffer
line = in.readUTF(); // getting response
System.out.println("The current time is : " + line);
}
}
}

Тут абсолютно все аналогічно (більш того, ми навіть відправляємо якийсь конкретний запит до сервера, щоб той таки міг ідентифікувати, що клієнт хоче дізнатися поточний час, а не випадково сюди забрів). Відповідь від сервера пишемо в консоль.

Нормальні люди зробили б все гламурненько потоками, щоб клієнт, наприклад, не вилітав з помилкою, якщо не зміг достукатися до сервера, а спробував кілька секунд почекати. А ще, як клієнтів кілька, то вони б могли на різні порти стукатися, а не ламатися всі в один. Це потім якось…

Почитайте ще оце:


Залиште коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

3 thoughts on “Проста клієнт-серверна муть на сокетах