?
??1
/**/
/*
??2
小高知宏?寫的書叫《TCP/IP?java篇》但我看起來,還想大都是應(yīng)用層上的東西
??3
好象應(yīng)該叫《TCP/IP?應(yīng)用層?java篇》?有點(diǎn)搞不清他的書名是從何而來的,呵呵!
??4
這是小高知宏的Telnet的客戶端程序,接下來我們看看它是怎么實(shí)現(xiàn)的
??5
*/
?
??6
??7
import
?java.net.
*
;
??8
import
?java.io.
*
;?
??9
?10
public
?
class
?Telnet?
{
?11
?Socket?serverSocket;????????????????
//
創(chuàng)建服務(wù)器端SOCKET
?12
?
public
?OutputStream?serverOutput;
?13
?
public
?BufferedInputStream?serverInput;
?14
?String?host;??????????????????
//
要連接的telnet服務(wù)器的地址或域名
?15
?
int
?port;?????????????????????
//
要連接的服務(wù)器端口?
?16
?17
?
static
?
final
?
int
?DEFAULT_TELNET_PORT?
=
?
23
;??
//
定義默認(rèn)的Telnet端口
?18
??
?19
??
//
構(gòu)造telnet的連接參數(shù)(含端口,就是當(dāng)你使用23以外的端口時(shí),調(diào)用這個(gè)函數(shù)體),有點(diǎn)像C的數(shù)據(jù)結(jié)構(gòu)
?20
?
public
?Telnet(String?host,?
int
?port)
{
?21
??
this
.host?
=
?host;????
//
這里不解釋了THIS的用法前面講過
?22
??
this
.port?
=
?port;
?23
?}
?24
??
//
定義默認(rèn)端口23對應(yīng)的函數(shù)體
?25
?
public
?Telnet(String?host)
{
?26
??
this
(host,?DEFAULT_TELNET_PORT);?
?27
?28
?
//
建立連接,將在客戶端輸入的數(shù)據(jù)host+port轉(zhuǎn)換成數(shù)據(jù)流
?29
?
public
?
void
?openConnection()
?30
??
throws
?IOException,UnknownHostException
?31
?
{?????????????????????????????????????????????????????????????????????????????????????
?32
??serverSocket?
=
?
new
?Socket(host,?port);?????
//
創(chuàng)建Socket????????????????????????????????????????
?33
??serverOutput?
=
?serverSocket.getOutputStream();???
//
獲取輸入數(shù)據(jù)
?34
??serverInput?
=
?
new
?BufferedInputStream(serverSocket.getInputStream());?
//
裝換數(shù)據(jù)
?35
??
if
?(port?
==
?DEFAULT_TELNET_PORT)
{??
//
判斷端口是不是23
?36
???negotiation(serverInput,?serverOutput);?
//
對輸出和輸入的數(shù)據(jù)進(jìn)行分析,實(shí)現(xiàn)C/S端口的協(xié)商
?37
??}
?38
?}
?
?39
?40
?
public
?
void
?main_proc()????
//
連接成功,啟動網(wǎng)絡(luò)線程
?41
??
throws
?IOException
?42
?
{
?43
??
try
?
{
?44
???
?45
???
//
生成線程的StreamConnector類的對象stdin_to_socket和socket_to_stdout
?46
???
//
從這里看出java是如何用類去創(chuàng)建對象的
?47
???StreamConnector?stdin_to_socket?
=
?48
????
new
?StreamConnector(System.in,?serverOutput);????
//
StreamConnector這個(gè)類在后面有定義
?49
???StreamConnector?socket_to_stdout?
=
?50
????
new
?StreamConnector(serverInput,?System.out);
?51
???
?52
???
//
生成對象對應(yīng)的stdin_to_socket和socket_to_stdout線程事件input_thread和output_thread
?53
???
//
看到j(luò)ava的事件是如何從對象中產(chǎn)生的
?54
???Thread?input_thread?
=
?
new
?Thread(stdin_to_socket);
?55
???Thread?output_thread?
=
?
new
?Thread(socket_to_stdout);
?56
???
?57
???
//
看看java如何啟動或調(diào)用事件
?58
???input_thread.start();
?59
???output_thread.start();
?60
??}
?61
??
//
整個(gè)過程可能會產(chǎn)生異常,這里進(jìn)行捕獲
?62
??
catch
(Exception?e)
{
?63
???System.err.print(e);
?64
???System.exit(
1
);
?65
??}
?66
?}
?67
??
//
定義用于協(xié)商的命令
?68
???
//
如果一個(gè)數(shù)據(jù)既是static又是final,那么他會擁有一塊無法改變的存儲空間
?69
?
static
?
final
?
byte
?IAC?
=
?(
byte
)?
255
;
?70
?
static
?
final
?
byte
?DONT?
=
?(
byte
)?
254
;
?71
?
static
?
final
?
byte
?DO?
=
?(
byte
)?
253
;
?72
?
static
?
final
?
byte
?WONT?
=
?(
byte
)?
252
;
?73
?
static
?
final
?
byte
?WILL?
=
?(
byte
)?
251
;?
?74
?75
??
//
利用NVT進(jìn)行通信
?76
??
/**/
/*
?77
??NVT是一種抽象的設(shè)備,由打印機(jī)和鍵盤組成。用戶使用鍵盤鍵入的字符被轉(zhuǎn)發(fā)到服務(wù)器中,
?78
??服務(wù)器再把數(shù)據(jù)返回給用戶,而NVT在打印機(jī)上將其輸出。它使用標(biāo)準(zhǔn)的回車與換行組合去
?79
??終止行。NVT提供控制操作,這些操作支持過程中斷并丟棄多余的輸出。這些操作是通過使
?80
??用IAC(Interpret?as?Command,解釋成命令)代碼發(fā)出的。IAC是一個(gè)單字節(jié),由值255或十
?81
??六進(jìn)制0xff組成。IAC后面可以跟著一個(gè)單字節(jié),用于發(fā)送控制代碼;或者后面跟著兩個(gè)或
?82
??更多的字節(jié),用于協(xié)商一選項(xiàng)。而為了發(fā)送已用于IAC的字節(jié)值255,可以通過一個(gè)特殊的字
?83
??節(jié)序列來實(shí)現(xiàn):連續(xù)發(fā)送兩個(gè)IAC。
?84
??JAVA實(shí)現(xiàn)應(yīng)用層的不少東西都是用他實(shí)現(xiàn)的?如:HTTP
?85
??
*/
?86
??
?87
?
static
?
void
?negotiation(
?88
??BufferedInputStream?in,OutputStream?out)
?89
??
throws
?IOException
?90
?
{
?91
??
byte
[]?buff?
=
?
new
?
byte
[
3
];????
//
接收數(shù)據(jù)
?92
??
while
(
true
)?
{
?93
???in.mark(buff.length);??
//
在此緩沖區(qū)的位置設(shè)置其標(biāo)記
?94
???
if
?(in.available()?
>=
?buff.length)?
{
?95
????in.read(buff);???
//
讀取緩沖區(qū)內(nèi)容
?96
????
if
?(buff[
0
]?
!=
?IAC)
{??
//
協(xié)商結(jié)束
?97
?????in.reset();????
//
將此緩沖區(qū)的位置重新設(shè)置成以前標(biāo)記的位置
?98
?????
return
;
?99
????}
?
else
?
if
?(buff[
1
]?
==
?DO)?
{????
//
用于對DO的回應(yīng)
100
?????buff[
1
]?
=
?WONT;
101
?????out.write(buff);
102
????}
103
???}
104
??}
105
?}
?
106
107
???
//
這里是主函數(shù)?
108
?
public
?
static
?
void
?main(String[]?arg)
{
109
??
try
?
{
110
???Telnet?t?
=
?
null
;????
//
創(chuàng)建Telnet變量
111
???
switch
?(arg.length)
{
112
???
case
?
1
:???
//
服務(wù)器名
113
????t?
=
?
new
?Telnet(arg[
0
]);
114
????
break
;
115
???
case
?
2
:??
//
服務(wù)器名+端口
116
????t?
=
?
new
?Telnet(arg[
0
],?Integer.parseInt(arg[
1
]));
117
????
break
;
118
???
default
:???
//
如果輸入格式不對
119
????System.out.println(
120
?????
"
usage:?java?Telnet?<host?name>?{<port?number>}
"
);
121
????
return
;
122
???}
123
???t.openConnection();??
//
連接
124
???t.main_proc();????
//
創(chuàng)建線程
125
??}
catch
(Exception?e)
{
126
???e.printStackTrace();
127
???System.exit(
1
);
128
??}
129
?}
130
}
?
131
132
//
定義StreamConnector類
133
//
定義前面的對象、事件的具體實(shí)現(xiàn)
134
class
?StreamConnector?
implements
?Runnable?
{
135
?InputStream?src?
=
?
null
;
136
?OutputStream?dist?
=
?
null
;?
137
138
//
接收參數(shù)
139
?
public
?StreamConnector(InputStream?in,?OutputStream?out)
{
140
??src?
=
?in;
141
??dist?
=
?out;
142
?}
143
//
用循環(huán)實(shí)現(xiàn)對數(shù)據(jù)流的讀寫
144
?
public
?
void
?run()
{
145
??
byte
[]?buff?
=
?
new
?
byte
[
1024
];???
//
一次處理的最大數(shù)據(jù)量
146
??
while
?(
true
)?
{
147
???
try
?
{
148
????
int
?n?
=
?src.read(buff);
149
????
if
?(n?
>
?
0
)
150
?????dist.write(buff,?
0
,?n);
151
???}
152
???
catch
(Exception?e)
{
153
????e.printStackTrace();
154
????System.err.print(e);
155
????System.exit(
1
);
156
???}
157
??}
158
?}
159
}
?
160


??2

??3

??4

??5

??6

??7

??8

??9

?10



?11

?12

?13

?14

?15

?16

?17

?18

?19

?20



?21

?22

?23

?24

?25



?26

?27

?28

?29

?30

?31



?32

?33

?34

?35



?36

?37

?38

?39

?40

?41

?42



?43



?44

?45

?46

?47

?48

?49

?50

?51

?52

?53

?54

?55

?56

?57

?58

?59

?60

?61

?62



?63

?64

?65

?66

?67

?68

?69

?70

?71

?72

?73

?74

?75

?76


?77

?78

?79

?80

?81

?82

?83

?84

?85

?86

?87

?88

?89

?90



?91

?92



?93

?94



?95

?96



?97

?98

?99



100

101

102

103

104

105

106

107

108



109



110

111



112

113

114

115

116

117

118

119

120

121

122

123

124

125



126

127

128

129

130

131

132

133

134



135

136

137

138

139



140

141

142

143

144



145

146



147



148

149

150

151

152



153

154

155

156

157

158

159

160

地震讓大伙知道:居安思危,才是生存之道。
