1
/**/
/*
2
小高知宏 写的书叫《TCP/IP java篇》但我看起来,还想大都是应用层上的东西
3
好象应该叫《TCP/IP 应用层 java篇》 有点搞不清他的书名是从何而来的,呵呵!
4
这是小高知宏的Telnet的客户端程序,接下来我们看看它是怎么实现的
5
*/
6
7
import
java.net.
*
;
8
import
java.io.
*
;
9
10
public
class
Telnet
{
11
Socket serverSocket;
//
创建服务器端SOCKET
12
public
OutputStream serverOutput;
13
public
BufferedInputStream serverInput;
14
String host;
//
要连接的telnet服务器的地址或域名
15
int
port;
//
要连接的服务器端口
16
17
static
final
int
DEFAULT_TELNET_PORT
=
23
;
//
定义默认的Telnet端口
18
19
//
构造telnet的连接参数(含端口,就是当你使用23以外的端口时,调用这个函数体),有点像C的数据结构
20
public
Telnet(String host,
int
port)
{
21
this
.host
=
host;
//
这里不解释了THIS的用法前面讲过
22
this
.port
=
port;
23
}
24
//
定义默认端口23对应的函数体
25
public
Telnet(String host)
{
26
this
(host, DEFAULT_TELNET_PORT);
27
28
//
建立连接,将在客户端输入的数据host+port转换成数据流
29
public
void
openConnection()
30
throws
IOException,UnknownHostException
31
{
32
serverSocket
=
new
Socket(host, port);
//
创建Socket
33
serverOutput
=
serverSocket.getOutputStream();
//
获取输入数据
34
serverInput
=
new
BufferedInputStream(serverSocket.getInputStream());
//
装换数据
35
if
(port
==
DEFAULT_TELNET_PORT)
{
//
判断端口是不是23
36
negotiation(serverInput, serverOutput);
//
对输出和输入的数据进行分析,实现C/S端口的协商
37
}
38
}
39
40
public
void
main_proc()
//
连接成功,启动网络线程
41
throws
IOException
42
{
43
try
{
44
45
//
生成线程的StreamConnector类的对象stdin_to_socket和socket_to_stdout
46
//
从这里看出java是如何用类去创建对象的
47
StreamConnector stdin_to_socket
=
48
new
StreamConnector(System.in, serverOutput);
//
StreamConnector这个类在后面有定义
49
StreamConnector socket_to_stdout
=
50
new
StreamConnector(serverInput, System.out);
51
52
//
生成对象对应的stdin_to_socket和socket_to_stdout线程事件input_thread和output_thread
53
//
看到java的事件是如何从对象中产生的
54
Thread input_thread
=
new
Thread(stdin_to_socket);
55
Thread output_thread
=
new
Thread(socket_to_stdout);
56
57
//
看看java如何启动或调用事件
58
input_thread.start();
59
output_thread.start();
60
}
61
//
整个过程可能会产生异常,这里进行捕获
62
catch
(Exception e)
{
63
System.err.print(e);
64
System.exit(
1
);
65
}
66
}
67
//
定义用于协商的命令
68
//
如果一个数据既是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进行通信
76
/**/
/*
77
NVT是一种抽象的设备,由打印机和键盘组成。用户使用键盘键入的字符被转发到服务器中,
78
服务器再把数据返回给用户,而NVT在打印机上将其输出。它使用标准的回车与换行组合去
79
终止行。NVT提供控制操作,这些操作支持过程中断并丢弃多余的输出。这些操作是通过使
80
用IAC(Interpret as Command,解释成命令)代码发出的。IAC是一个单字节,由值255或十
81
六进制0xff组成。IAC后面可以跟着一个单字节,用于发送控制代码;或者后面跟着两个或
82
更多的字节,用于协商一选项。而为了发送已用于IAC的字节值255,可以通过一个特殊的字
83
节序列来实现:连续发送两个IAC。
84
JAVA实现应用层的不少东西都是用他实现的 如:HTTP
85
*/
86
87
static
void
negotiation(
88
BufferedInputStream in,OutputStream out)
89
throws
IOException
90
{
91
byte
[] buff
=
new
byte
[
3
];
//
接收数据
92
while
(
true
)
{
93
in.mark(buff.length);
//
在此缓冲区的位置设置其标记
94
if
(in.available()
>=
buff.length)
{
95
in.read(buff);
//
读取缓冲区内容
96
if
(buff[
0
]
!=
IAC)
{
//
协商结束
97
in.reset();
//
将此缓冲区的位置重新设置成以前标记的位置
98
return
;
99
}
else
if
(buff[
1
]
==
DO)
{
//
用于对DO的回应
100
buff[
1
]
=
WONT;
101
out.write(buff);
102
}
103
}
104
}
105
}
106
107
//
这里是主函数
108
public
static
void
main(String[] arg)
{
109
try
{
110
Telnet t
=
null
;
//
创建Telnet变量
111
switch
(arg.length)
{
112
case
1
:
//
服务器名
113
t
=
new
Telnet(arg[
0
]);
114
break
;
115
case
2
:
//
服务器名+端口
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();
//
创建线程
125
}
catch
(Exception e)
{
126
e.printStackTrace();
127
System.exit(
1
);
128
}
129
}
130
}
131
132
//
定义StreamConnector类
133
//
定义前面的对象、事件的具体实现
134
class
StreamConnector
implements
Runnable
{
135
InputStream src
=
null
;
136
OutputStream dist
=
null
;
137
138
//
接收参数
139
public
StreamConnector(InputStream in, OutputStream out)
{
140
src
=
in;
141
dist
=
out;
142
}
143
//
用循环实现对数据流的读写
144
public
void
run()
{
145
byte
[] buff
=
new
byte
[
1024
];
//
一次处理的最大数据量
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
小寻 阅读(855)
评论(0) 编辑 收藏 所属分类:
j2se/j2ee/j2me