?
??1
/**/
/*
??2
小高知宏?寫(xiě)的書(shū)叫《TCP/IP?java篇》但我看起來(lái),還想大都是應(yīng)用層上的東西
??3
好象應(yīng)該叫《TCP/IP?應(yīng)用層?java篇》?有點(diǎn)搞不清他的書(shū)名是從何而來(lái)的,呵呵!
??4
這是小高知宏的Telnet的客戶端程序,接下來(lái)我們看看它是怎么實(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的用法前面講過(guò)
?22
??
this
.port?
=
?port;
?23
?}
?24
??
//
定義默認(rèn)端口23對(duì)應(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);?
//
對(duì)輸出和輸入的數(shù)據(jù)進(jìn)行分析,實(shí)現(xiàn)C/S端口的協(xié)商
?37
??}
?38
?}
?
?39
?40
?
public
?
void
?main_proc()????
//
連接成功,啟動(dòng)網(wǎng)絡(luò)線程
?41
??
throws
?IOException
?42
?
{
?43
??
try
?
{
?44
???
?45
???
//
生成線程的StreamConnector類的對(duì)象stdin_to_socket和socket_to_stdout
?46
???
//
從這里看出java是如何用類去創(chuàng)建對(duì)象的
?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
???
//
生成對(duì)象對(duì)應(yīng)的stdin_to_socket和socket_to_stdout線程事件input_thread和output_thread
?53
???
//
看到j(luò)ava的事件是如何從對(duì)象中產(chǎn)生的
?54
???Thread?input_thread?
=
?
new
?Thread(stdin_to_socket);
?55
???Thread?output_thread?
=
?
new
?Thread(socket_to_stdout);
?56
???
?57
???
//
看看java如何啟動(dòng)或調(diào)用事件
?58
???input_thread.start();
?59
???output_thread.start();
?60
??}
?61
??
//
整個(gè)過(guò)程可能會(huì)產(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,那么他會(huì)擁有一塊無(wú)法改變的存儲(chǔ)空間
?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ī)和鍵盤(pán)組成。用戶使用鍵盤(pán)鍵入的字符被轉(zhuǎn)發(fā)到服務(wù)器中,
?78
??服務(wù)器再把數(shù)據(jù)返回給用戶,而NVT在打印機(jī)上將其輸出。它使用標(biāo)準(zhǔn)的回車(chē)與換行組合去
?79
??終止行。NVT提供控制操作,這些操作支持過(guò)程中斷并丟棄多余的輸出。這些操作是通過(guò)使
?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,可以通過(guò)一個(gè)特殊的字
?83
??節(jié)序列來(lái)實(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)?
{????
//
用于對(duì)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
:???
//
如果輸入格式不對(duì)
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
//
定義前面的對(duì)象、事件的具體實(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)對(duì)數(shù)據(jù)流的讀寫(xiě)
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
地震讓大伙知道:居安思危,才是生存之道。
posted on 2007-03-09 00:14
小尋 閱讀(862)
評(píng)論(0) 編輯 收藏 所屬分類:
j2se/j2ee/j2me