TCP сокети
Както вече знаем от краткия преглед на Интернет протоколите, който направихме в началото, TCP сокетите представляват надежден двупосочен транспортен канал за данни между две приложения. Приложенията, които си комуникират през сокет, могат да се изпълняват на един и същ компютър или на различни компютри, свързани по между си чрез Интернет или друга TCP/IP мрежа. Тези приложения биват два вида – сървъри и клиенти. Клиентите се свързват към сървърите по IP адрес и номер на порт чрез класа java.net.Socket. Сървърите приемат клиенти чрез класа java.net.ServerSocket. При разработка на сървъри обикновено трябва да се съобразяваме с необходимостта от обслужване на много потребители едновременно и независимо един от друг. Най-често този проблем се решава с използване на нишки за всеки потребител. Нека първо разгледаме по-простия вариант – обслужване само на един клиент в даден момент.
Прост TCP сървър
Да разгледаме сорс-кода на едно просто сървърско приложение – DateServer:
CODE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//DateServer.java
import java.util.Date;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
public class DateServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(2002);
while (true) {
Socket socket = serverSocket.accept();
OutputStreamWriter out =
new OutputStreamWriter(
socket.getOutputStream());
out.write(new Date()+ "n");
out.close();
socket.close();
}
}
} |
Този сървър отваря за слушане TCP порт 2002, след което в безкраен цикъл приема клиенти, изпраща им текущата дата и час и веднага след това затваря сокета с тях. Отварянето на сокет за слушане става като се създава обект от класа ServerSocket, в конструктора на който се задава номера на порта. Приемането на клиент се извършва от метода accept() на класа ServerSocket, при извикването на който текущата нишка блокира до пристигането на клиентска заявка, след което създава сокет връзка между сървъра и пристигналия клиент. От създадената сокет връзка сървърът взема изходния поток за изпращане на данни към клиента (чрез метода getOutputStream()) и изпраща в него текущата дата и час, записани на една текстова линия. Затварянето на изходния поток е важно. То предизвиква действителното изпращане на данните към клиента, понеже извиква метода flush() на изходния поток. Ако нито един от методите close() или flush() не бъде извикан, клиентът няма да получи нищо, защото изпратените данни ще останат в буфера на сокета и няма да отпътуват по него. Накрая, затварянето на сокета предизвиква прекъсване на комуникацията с клиента. Сървърът можем да изтестваме със стандартната програмка telnet, която е включена в повечето версии на Windows, Linux и Unix като напишем на конзолата следната команда:
CODE
Резултатът е получената от сървъра дата:
CODE1
2
|
Wed Mar 03 20:31:05 EET 2004 |