java的socket编程---telnet客户端的实现

//telnet 的命令格式:IAC+命令码+选项码
final byte IAC=(byte)255;

//协商的命令码
final byte DONT=(byte)254;
final byte DO=(byte)253;
final byte WONT=(byte)252;
final byte WILL=(byte)251;
final byte SB=(byte)250;
final byte SE=(byte)240;

//协商的选项码
final char IS = '0';
final char SEND = '1';
final char INFO = '2';
final char VAR = '0';
final char VALUE = '1';
final char ESC = '2';
final char USERVAR = '3';

final int MAX=1000000;

Socket s;
InputStream in;
OutputStream out;
PrintStream ps;
DataInputStream conIn;
BufferedInputStream dataIn;

// String sysIn="open\r\n";	
byte[] recvByte;	//接收的字节数据
String recv;	//转换后的字符
byte[] sendByte;	//发送的字节数据
String send;	//发送的源字符
int read;	//接收的字节数据的个数
int write;	//发送的字节数据个数
boolean hasData;	//标志套接字中的输入流是否还有未读完的数据

String ip;
int port;

public Socket2Telnet(Socket s,String ip,int port){
this.s=s;
this.ip=ip;
this.port=port;
}

//关闭socket连接
public void closeConnection(Socket s,InputStream in,OutputStream out){
if(s.isConnected()&&!s.isClosed()){
try {
in.close();
out.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


//解析协商数据
public void Compile(){
//存在协商控制命令选项时需要解析并应答
write=0;
for(int i=0;i<read;){
if(recvByte[i]==IAC){	//255
//	System.out.println("get IAC!"+(int)(recvByte[0]& 0xff)+recvByte[0]);
sendByte[write]=recvByte[i];

if(recvByte[i+2]==1||recvByte[i+2]==3){

if(recvByte[i+1]==DO){	//253
//	System.out.println("get DO!"+(int)(recvByte[1]& 0xff));

sendByte[write+1]=WILL;
sendByte[write+2]=recvByte[i+2];
write+=3;
i+=3;
}else 
if(recvByte[i+1]==WILL){	//251
//	System.out.println("get WILL !"+(int)(recvByte[1]& 0xff)+recvByte[1]);

sendByte[write+1]=DO;
sendByte[write+2]=recvByte[i+2];
write+=3;
i+=3;
}else
if(recvByte[i+1]==WONT){	//252
//	System.out.println("get WONT!"+(int)(recvByte[1]&0xff)+recvByte[1]);

sendByte[write+1]=DONT;
sendByte[write+2]=recvByte[i+2];
write+=3;
i+=3;
}else
if(recvByte[i+1]==DONT){	//254
//	System.out.println("get DONT! "+(int)(recvByte[1]&0xff)+recvByte[1]);

sendByte[write+1]=WONT;
sendByte[write+2]=recvByte[i+2];
write+=3;
i+=3;
}else
if(recvByte[i+1]==SB){	//250
System.out.println("get SB ! "+(int)(recvByte[1]&0xff)+recvByte[1]);

if(recvByte[i+3]==SEND){
System.out.println("get SEND!"+recvByte[3]);
sendByte[write+1]=recvByte[i+1];
sendByte[write+2]=recvByte[i+2];
sendByte[write+3]=IS;
sendByte[write+4]=IAC;
sendByte[write+5]=SE;
System.out.println("YES, get a SD and SEND !");
write+=6;
i+=3;
}
}
//	System.out.println(" and recvByte[2] "+(int)(recvByte[2]&0xff)+recvByte[2]+(char)(recvByte[2]&0xff));

//	ps.write(sendByte,0,write);
//	ps.flush();
}else{
if(recvByte[i+1]==DONT||recvByte[i+1]==DO){
sendByte[write+1]=WONT;
sendByte[write+2]=recvByte[i+2];
}
else if(recvByte[i+1]==WILL||recvByte[i+1]==WONT){
sendByte[write+1]=DONT;
sendByte[write+2]=recvByte[i+2];
}
write+=3;
i+=3;
}
}else{
return;
}
}
}


//sokcet连接服务器,收发数据
public void run(){
try {
s.connect(new InetSocketAddress(ip,port));
System.out.println("socket Connect success!");
System.out.println("Server IP:"+s.getInetAddress()+",port :"+s.getPort()+"\n");

//获取套接字的输入和输出流
in=s.getInputStream();
out=s.getOutputStream ();

conIn=new DataInputStream(System.in);
dataIn=new BufferedInputStream(in);
ps=new PrintStream(out);

//初始化
recvByte=new byte[MAX];
sendByte=new byte[MAX];
recv=new String("");
send=new String("");
write=read=0;


while(true){

read=write=0;

Thread.sleep(2000);

if((read=in.read(recvByte))>0){
hasData=true;
}else
hasData=false;

//	System.out.println("recv data "+read+" byte!");
//	System.out.println("recv msg :"+new String(recvByte,"UTF-8"));

//	for(int i=0;i<read;i++)
//	System.out.print((char)(recvByte[i]&0xff));
//	System.out.println("");
for(int i=0;i<read;i++)
System.out.print((int)(recvByte[i]&0xff)+" ");
System.out.println("\n");

//协商的应答
if(read>0){
Compile();
if(write>0){
ps.write(sendByte,0,write);
//	ps.flush();
}
}

System.out.println("read = "+read+",write = "+write);
Thread.sleep(3000);

//服务器没有响应时,等待用户输入命令;
//服务器返回输入命令时,告知用户命令,并读取用户输入并发送给服务器;
send="";
if(read<=0||read>write){
System.out.println(read>0?"recv msg:"+new String(recvByte,write,read-write,"UTF-8"):"");
if(read==2) System.out.println("recv two data:"+(recvByte[0]&0xff)+(recvByte[1]&0xff));

Scanner sc=new Scanner(System.in);
send=sc.nextLine()+"\r\n";
//	send=conIn.readLine()+"\r\n";

if("exit".equals(send)){
closeConnection(s,in,out);
return;
}
System.out.println("send msg :"+send);

ps.write(send.getBytes("ISO-8859-1"));
//	ps.flush();
System.out.println("send over!");	
}

ps.flush();
}
} catch (IOException e) {
System.out.println("Client Connected Failed :\t");
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("Thread Error!");
e.printStackTrace();
}finally{
closeConnection(s,in,out);
}
}
}

最近在写一个telnet客户端的代码,要求使用socket进行通讯而不是apache的工具包。遂本人在网上找了很多文档,结果发现和之前写的socket实时通讯的工具很像。于是我就毫不思索的将代码copy了一遍,结果运行时悲剧了。每次的socket连接自然没有问题,但是就是没有回应,我这边发送了数据,也没响应。

于是就郁闷了,本人是使用windows环境,telnet虚拟机的open solaris,可是不管怎么调试和修改,就是接受不到数据。没办法只能卡住了,把telnet协议和socket通讯又是一遍一遍的看,网上狂找文档,终于明白了问题的关键。socket通讯可以实现客户端和服务器进行通讯和数据传输,比如ftp,smtp等都可以,但是对于telnet而言,telnet时远程登陆的工具,它是跨平台的(WINDOWSH、LINUX等),因此在通讯时需要将数据和命令转换成双方约定好的格式(NVT,关于NVT这里不多讲,有个故事很形象的描述了这个问题)。

其实最重要的是了解telnet登陆时的细节,telnet在连接时,需要客户端和服务器进行协商,也就是双方规定发送数据的”标准“。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值