Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги хакеры / Защита_от_взлома_сокеты,_эксплойты,_shell_код_Фостер_Дж_

.pdf
Скачиваний:
14
Добавлен:
19.04.2024
Размер:
3.68 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

Обзор протоколов ТСР/IP 241

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

 

 

p

 

-x cha

 

 

 

 

 

 

 

-xchзатьсяa

нужным при разработке TCP-сервера, допускающего анонимное со-

 

 

e

 

 

 

 

df

 

 

n

e

 

 

 

 

df

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

единение со стороны клиента, адрес которого вы хотите запротоколировать и, возможно, связаться с ним.

Пример 5.3. Получение информации об IP*адресе от активного TCP*соединения

1 InetAddress inetaddr1 = null;

2 InetAddress inetaddr2 = null;

3 Socket sock = null;

4

5 try

6 {

7 sock = new Socket("127.0.0.1", 80);

8

9inetaddr1 = sock.getLocalAddress();

10 inetaddr2 = sock.getInetAddress ();

11

12System.out.println(inetaddr1);

13System.out.println(inetaddr2);

14}

15catch (UnknownHostException uhe)

16{

17System.err.println("UnknownHostException:

18

+ uhe.getMessage());

19}

20catch (IOException ioe)

21{

22System.err.println("IOException " + ioe.getMessage());

23}

Если откомпилировать эту программу и запустить ее для связи с сервером TCPServer1 (см. пример 5.5), работающим на порту 80 локального компьютера, то будут напечатаны показанные ниже строки. Важно отметить, что если этот клиент связывается с удаленным сервером, то второй IP-адрес (адрес сервера) не будет совпадать с первым (адресом клиента).

Пример выполнения

C:/> TCPServer1 80

*** прослушивается порт 80

.

.

C:/> java Example3.java 127.0.0.1 80 /

/127.0.0.1

/127.0.0.1

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

242 Глава 5. Сокеты в языке Java

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

-xcha

 

 

.c

 

 

 

p

 

 

 

Анализ

 

 

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

В строке 7 клиентский TCP-сокет соединяется с портом 80 по адресу 127.0.0.1.

В строке 9 мы получаем IP-адрес локальной оконечной точки соединения в виде объекта типа InetAddress. В этом примере и клиент, и сервер находятся на компьютере localhost, поэтому IP-адреса локальной и удаленной оконечных точек совпадают и равны 127.0.0.1. В общем случае они, конечно, могут различаться.

В строке 10 извлекается IP-адрес удаленной оконечной точки, тоже

âвиде объекта InetAddress. В данном случае он равен 127.0.0.1.

В строках 12–13 IP-адреса локальной и удаленной оконечных точек выводятся на печать.

В строке 15 обрабатывается исключение UnknownHostException, которое возбуждает конструктор класса Socket, если не может разрешить переданное ему имя хоста.

В строке 20 обрабатывается исключение IOException, возбуждаемое

âслучае ошибки при установлении соединения, передаче данных или разрыва соединения.

Разрешение IP-адресов, представленных в точечно-десятичной нотации, является «неблокирующей» операцией. Разрешение же имен хостов, к примеру, CHIAPAS (см. пример 5.2) – это блокирующая операция, для ее выполнения нужно обратиться к службе DNS, что может занять несколько секунд.

Ввод/вывод текста: класс LineNumberReader

При работе с текстовыми протоколами, например, HTTP, POP3 (Post Office Protocol), IMAP (Internet Message Access Protocol) или FTP (File Transfer Protocol) удобно рассматривать принимаемые данные, как текстовые строки, а не массивы байтов. В пакете java.io есть класс LineNumberReader, с помощью которого легко читать строки текста из сокета.

Для этого надо выполнить следующие действия:

1.Получить от соединенного сокета объект типа InputStream.

2.Надстроить над ним объект типа InputStreamReader.

3.Над объектом InputStreamReader надстроить объект типа

LineNumberReader.

После того как объект LineNumberReader создан, можно воспользоваться им для чтения строк.

Пример 5.4 основывается на примере 5.3, но добавляет возможность построчно читать и выводить на печать ответ, полученный от Web-сервера. Конечно, это очень простая программа, но вместе с тем полезная, так как ей

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

Обзор протоколов ТСР/IP 243

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

 

 

p

 

-x cha

 

 

 

 

 

 

 

-xchможноa

воспользоваться в более сложных приложениях для считывания шапок,

 

 

e

 

 

 

 

df

 

 

n

e

 

 

 

 

df

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

сканирования уязвимостей, написания прокси-серверов и Web-эксплойтов.

Пример 5.4. Применение класса LineNumberReader в клиентской программе (TCPClient2.java)

1 /*

2 * TCPClient2.java

3*

4* TCP-клиент, который устанавливает соединение,

5* посылает запрос по протоколу HTTP 1.0,

6* принимает данные построчно с помощью класса LineNumberReader

7 * и выводит результат на печать.

8*

9 * Порядок запуска:

10*

11* java TCPClient2 <target_ip> <target_port> <resource>

12*

13*

14*/

15import java.io.* ;

16import java.net.*;

17

18 public class TCPClient2

19{

20public static void main(String[] args)

21{

22

23

InputStreamReader

isr

= null;

24

LineNumberReader

lnr

= null;

25

InputStream

is

= null;

26

OutputStream

os

= null;

27

Socket

sock

= null;

28

String

addr

= null;

29

String

res

= null;

30

String

send

= null;

31

String

tmp

= null;

32

byte[]

recv

= new byte[4096];

33

int

port

= 0;

34

int

x

= 0;

35

 

 

 

36if(args.length != 3)

37{

38System.err.println("usage: java TCPClient2 " +

39

"<target_ip> <target_port> " +

 

40

"<resource>.");

 

41

System.err.println("Пример: java

TCPClient2 "

+

42

"127.0.0.1 80

/");

 

43

System.exit(1);

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

244 Глава 5. Сокеты в языке Java

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

m

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

e

 

}

 

 

 

df-xchan

44

 

 

 

 

 

 

 

 

45

 

46addr = args[0];

47tmp = args[1];

48res = args[2];

50try

51{

52// преобразовать номер порта в числовое значение

53port = Integer.parseInt(tmp);

54

55// соединиться с IP-адресом и портом

56sock = new Socket(addr, port);

57

58// получить от сокета поток вывода

59os = sock.getOutputStream();

60

61// подготовить HTTP-запрос

62send = "GET " + res + " HTTP/1.0\r\n\r\n";

64// отправить HTTP-запрос

65os.write(send.getBytes());

67// получить от сокета поток ввода

68is = sock.getInputStream ();

69

70// сконструировать объект LineNumberReader

71isr = new InputStreamReader(is );

72lnr = new LineNumberReader (isr);

73

74// читать ответ построчно и выводить на печать

75x = 0;

76while((tmp = lnr.readLine()) != null)

77{

78System.out.println(x + ") " + tmp);

79++x;

80}

81

82// закрыть соединение

83sock.close();

84}

85catch (NumberFormatException nfe)

86{

87// нечисловое значение?

88System.err.println("NumberFormatException: "

89

+ nfe.getMessage());

90}

91catch (IOException ioe)

92{

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

d

 

 

F

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

 

m

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

e

 

 

 

 

df-xch93an

 

 

 

 

 

 

 

94

 

 

95

96 }

97 }

98 }

99

// ошибка при установлении соединения? System.err.println("IOException: "

+ ioe.getMessage());

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Обзор протоколов ТСР/IP 245

 

to

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Компиляция

C:\> j2sdk1.4.1_02\bin\javac.exe TCPClient2.java

C:\> dir

.

.

TCPClient2.class

.

.

Пример выполнения

C:\> j2sdk1.4.1_02\bin\java.exe TCPClient2.java

usage: java TCPClient2 <target_ip> <target_port> <resource> Пример: java TCPClient2 127.0.0.1 80 /

C:\> j2sdk1.4.1_02\bin\java.exe TCPClient2.java www.insidiae.org 80 /

0)HTTP/1.0 200 OK

1)Server: thttpd/.23beta1 26 may 2002

2)Content-Type: text/html; charset=iso-8859-1

3)Date: Mon, 26 May 2003 17:02:29 GMT

4)Last-Modified: Thu, 08 May 2003 19:30:33 GMT

5)Accept-Ranges: bytes

6)Connection: close

7)Content-Length: 339

Âпримере 5.4 создается клиентский TCP-сокет, с помощью которого устанавливается соединение с HTTP-сервером, работающим на порту 80. Затем серверу посылается стандартный запрос GET HTTP/1.0 и построчно читается ответ (здесь-то и пригодился класс LineNumberReader), который далее выводится на stdout, в данном случае в окно команд.

Анализ

В строках 1–56 выполняются те же предварительные действия, что и в программе TCPClient1. Обрабатываются аргументы, заданные в ко-

мандной строке, создается объект Socket, который затем соединяется с указанными IP-адресом и портом.

246 Глава 5. Сокеты в языке Java

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

В строках 59–65 у объекта Socket запрашивается поток вывода Output--x cha

 

e

 

 

 

 

df

 

 

n

 

 

 

 

 

 

 

 

 

 

Stream, конструируется HTTP-запрос, который затем отправляется удаленному хосту.

В строках 68–72 у объекта Socket запрашивается поток ввода InputStream, над ним надстраивается объект InputStreamReader, а над последним –

LineNumberReader.

В строках 75–80 объект LineNumberReader используется для того, чтобы прочитать построчно ответ, полученный от сервера. Каждая строка выводится на stdout, причем ей предшествует порядковый номер.

В строках 82–98выполняется та же очистка, что в программе TCPClient1. Сокет закрывается, при этом разрывается соединение. Обрабатываются возможные исключения.

До сих пор мы занимались простыми клиентскими программами, в которых сокет был представлен объектом класса Socket. Мы познакомились с несколькими вариантами разрешения IP-адресов и имен хостов и видели, как можно построчно читать данные, посылаемые удаленным компьютером. (Отметим, что процедуры приема и вывода на печать данных, получаемых от TCP и от UDP-сервера, очень похожи.) В следующем разделе мы познакомимся с созданием серверных TCP-сокетов, которые могут получать запросы на соединение от таких клиентов, как TCPClient1 èëè TCPClient2.

TCP3серверы

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

В классе ServerSocket определено несколько конструкторов для привязки сокета к локальному IP-адресу и порту и задания размера очереди входящих соединений. Остальные методы служат для приема новых запросов на соединение, тонкой настройки различных аспектов сокета, выяснения текущего состояния и закрытия сокета.

Для реализации базовой функциональности серверного TCP-сокета нужно не так уж много конструкторов и методов. В примере 5.5 класс LineNumberReader используется для построчного чтения запроса от клиента. Отметим, что этот сервер однопоточный, причем после обработки первого же запроса он закрывает сокет и завершается.

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

 

.c

 

5.5.

 

 

p

 

-xchПримерa

 

 

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Обзор протоколов ТСР/IP 247

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

Серверный TCP*сокет (TCPServer1.java)

 

.

 

-x cha

 

.c

 

 

 

p

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

1 /*

2 * TCPServer1.java

3*

4* Программа создает серверный TCP-сокет, привязывает его к порту,

5

*

ожидает запроса по протоколу HTTP, печатает его и посылает

6

*

ответ.

7*

8 * Порядок запуска:

9*

10* java TCPServer1 <local_port>

11*

12*

13*/

14

15 import java.io.* ;

16 import java.net.*;

17

18 public class TCPServer1

19{

20public static void main(String[] args)

21{

22InputStreamReader isr = null;

23LineNumberReader lnr = null;

24

OutputStream

os

= null;

25

ServerSocket

serv

= null;

26

InputStream

is

= null;

27

Socket

clnt

= null;

28

String

send

= null;

29

String

tmp

= null;

30

int

port

= 0;

31

int

x

= 0;

32

 

 

 

33if(args.length != 1)

34{

35System.err.println("usage: java " +

36

"TCPServer1 <local_port>");

37System.err.println("Пример: java TCPServer1 80");

38System.exit(1);

39}

40

41 tmp = args[0];

42

43try

44{

45// преобразовать номер порта в числовое значение

46port = Integer.parseInt(tmp);

47 48 // создать сокет, привязать его и начать прослушивать порт

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

248 Глава 5. Сокеты в языке Java

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

m

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

e

 

serv = new ServerSocket(port);

 

 

 

df-xchan

49

 

 

 

 

 

 

 

 

50

 

 

 

 

 

 

 

 

 

51

System.out.println("*** прослушивается порт " + port);

 

 

 

 

 

 

 

 

52

 

53// принять запрос на новое соединение

54clnt = serv.accept();

55

56

//

получить поток ввода

57

is

= clnt.getInputStream ( );

58

 

 

59// надстроить над ним объект LineNumberReader

60isr = new InputStreamReader(is );

61lnr = new LineNumberReader (isr);

62

63// прочитать запрос

64x = 0;

65while((tmp = lnr.readLine()) != null)

66{

67System.out.println(x + ") " + tmp);

68++x;

69

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

70// обработать пустую строку, служащую разграничителем в HTTP

71if(tmp.length() == 0)

72{

73break;

74}

75}

76

77// получить поток вывода

78os = clnt.getOutputStream();

80// отправить запрос

81send = "HTTP/1.0 200 OK\r\n\r\nTCPServer1!";

83

os.write(send.getBytes());

84

 

85// разорвать соединение с клиентом

86clnt.close();

87

88// закрыть серверный сокет

89serv.close();

90}

91catch (NumberFormatException nfe)

92{

93// нечисловое значение номера порта?

94System.err.println("NumberFormatException: "

95

+ nfe.getMessage());

96}

97catch(IOException ioe)

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

d

 

 

 

 

F

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

i

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

 

{

 

 

 

df-xchan98

 

 

 

 

 

 

 

 

99

 

 

// ошибка при работе с сокетом?

 

 

 

 

 

100

 

 

System.err.println("IOException: "

 

 

 

 

 

101

 

 

+ ioe.getMessage());

102}

103}

104}

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Обзор протоколов ТСР/IP 249

 

to

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Компиляция

C:\> j2sdk1.4.1_02\bin\javac.exe TCPServer1.java

C:\> dir

.

.

TCPServer1.class

.

.

Пример выполнения

C:\> j2sdk1.4.1_02\bin\java.exe TCPServer1

usage: java TCPServer1 <local_port> Пример: java TCPServer1 80

***прослушивается порт 80

Âпримере 5.5 мы создаем серверный сокет, привязываем его к порту, заданному в командной строке, и используем для приема входящих соединений. Клиентский сокет, созданный в результате приема соединения, применяется для чтения запроса по протоколу HTTP 1.0 и отправки ответа.

Анализ

В строках 33–38 обрабатывается номер порта, заданный в командной строке.

В строке 46 номер порта преобразуется в числовое значение методом parseInt() класса Integer.

В строке 49 конструктор класса ServerSocket создает сокет, привязывает его к порту и переводит в режим ожидания входящих соединений. В отличие от других сетевых API, скажем, BSD-сокетов, конструктор классаServerSocket выполняет операции bind è listen çà îäèí øàã.

В строке 54 вызывается метод accept() для приема нового соединения. Этот метод блокирующий, то есть он не возвращает управление, пока не придет запрос. Как только запрос получен, метод accept() возвраща-

ет объект класса Socket, представляющий новое соединение.

250 Глава 5. Сокеты в языке Java

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

g

.c

 

 

 

p

 

 

 

 

 

 

 

В строках 57–61 с помощью метода getInputStream() мы получаем поток-x cha

 

e

 

 

 

 

df

 

 

n

 

 

 

 

 

 

 

 

 

 

InputStream, соответствующий соединению с клиентом, а затем надстраиваем над ним объект LineNumberReader, позволяющий извлекать из потока строки текста в коде ASCII.

В строках 63–75 запрос от клиента считывается построчно с помощью объекта LineNumberReader, и прочитанные строки выводятся на stdout.

В строке 78 мы с помощью метода getOutputStream() получаем выходной поток OutputStream.

В строке 81 в переменной send конструируется ответ по протоколу HTTP 1.0.

В строке 83 переменная send преобразуется в массив байтов с помощью метода getBytes() класса String, и этот массив отправляется клиенту методом write() класса OutputStream.

В строке 86 соединение с клиентом закрывается методом close() класса Socket. После этого сокет уже нельзя использовать для приема или передачи данных.

В строке 89 закрывается серверный сокет, для чего вызывается метод close() класса ServerSocket. Больше сервер не будет принимать новых запросов на соединение от клиентов.

В строке 91 обрабатывается исключение типа NumberFormatException. Такое исключение возникает, если в командной строке указан некорректный номер порта.

В строке 97 обрабатывается исключение типа IOException, возбуждаемое в случае возникновения ошибки при работе с соединением как методами класса Socket, так и методами класса ServerSocket.

Использование Web3браузера

для соединения с сервером TCPServer1

Сервер из примера 5.5 может возвращать данные, как и всякий другой Webсервер. Мы можем соединиться с ним из любого стандартного браузера (рис. 5.1). Ниже показан протокол сеанса обмена данными между сервером TCPServer1 и браузером Microsoft Internet Explorer for Windows:

SYNGRESS# java TCPServer1 80

*** прослушивается порт 80

0)GET / HTTP/1.1

1)Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/ msword, */*

2)Accept-Language: en-us

3)Accept-Encoding: gzip, deflate

4) User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)