JAVA通过TCP编程模拟telnet程序

来源:互联网 发布:崔成国 知乎 编辑:程序博客网 时间:2024/06/10 02:19

下面简单通过一个TCP客户端及服务端程序,来模拟我们常用的telnet程序的回应功能,即客户端输入哪些内容,服务端经过简单字符串处理进行响应。

简介:在java中使用Socket,即套接字完成TCP程序的开发,使用此类与服务器建立可靠,双向,持续,点对点的通信连接,在socket程序开发中,服务端使用serversocket等待客户端连接,而所有客户端通过socket对象与服务端建立连接,下边简单列出ServerSocket 与 socket常用API:

ServerSocket:

构造函数
ServerSocket()throws IOException
ServerSocket(int port)throws IOException
ServerSocket(int port, int backlog)throws IOException
ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException
注意点:
1. port服务端要监听的端口;backlog客户端连接请求的队列长度(默认50);bindAddr服务端绑定IP
2. 如果端口被占用或者没有权限使用某些端口会抛出BindException错误。譬如1~1023的端口需要管理员才  拥有权限绑定。
3. 如果设置端口为0,则系统会自动为其分配一个端口;
4. bindAddr用于绑定服务器IP,为什么会有这样的设置呢,譬如有些机器有多个网卡。
   5. ServerSocket一旦绑定了监听端口,就无法更改。ServerSocket()可以实现在绑定端口前设置其他的      参数。
Socket:

构造函数
Socket()

Socket(InetAddress address, int port)throws UnknownHostException, IOException
Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException
Socket(String host, int port)throws UnknownHostException, IOException
Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException

getInetAddress();      远程服务端的IP地址
getPort();          远程服务端的端口
getLocalAddress()      本地客户端的IP地址
getLocalPort()        本地客户端的端口
getInputStream();     获得输入流
getOutStream();      获得输出流
值得注意的是,在这些方法里面,最重要的就是getInputStream()和getOutputStream()了。
 
Socket状态
isClosed();            //连接是否已关闭,若关闭,返回true;否则返回false
isConnect();      //如果曾经连接过,返回true;否则返回false
isBound();            //如果Socket已经与本地一个端口绑定,返回true;否则返回false
如果要确认Socket的状态是否处于连接中,下面语句是很好的判断方式。
boolean isConnection=socket.isConnected() && !socket.isClosed();   //判断当前是否处于连接


如下是本节示例代码,

服务端代码:

package com.ray.tcp.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * Echo服务端代码
 * @author ray
 *
 */
public class EchoServer {


public static void main(String[] args) {
ServerSocket server = null; //服务端实例
Socket client = null;//客户端实例

PrintStream out = null;//用于响应客户端
BufferedReader in = null;//读取客户端发送过来的请求报文

try {
server = new ServerSocket(8888); //实例化服务器,并指定端口8888

while(true){
client = server.accept();//等待客户端连接请求
in = new BufferedReader(new InputStreamReader(client.getInputStream()));  //获取客户端输入的数据
out = new PrintStream(client.getOutputStream()); //向客户端响应数据

boolean isEnd = false;
while(!isEnd){
String tmp = in.readLine();
System.out.println("client echo: " + tmp);
if(tmp != null && !"bye".equalsIgnoreCase(tmp.trim())){
out.println("server echo: " + tmp);
} else {
isEnd = true;
}
}
in.close(); //关闭客户端输入流
out.close(); //关闭客户端输出流
client.close();//与客户端断开连接

}


} catch (IOException e) {
e.printStackTrace();
} finally {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


客户端代码:

package com.ray.tcp.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * Echo 客户端代码,模拟telnet发送TCP报文
 * @author ray
 *
 */
public class EchoClient {
public static void main(String[] args) {

Socket client = null;//客户端实例
BufferedReader input = null;//接受键盘输入的消息
BufferedReader in = null;//接受服务器响应的数据

PrintStream out = null;//向服务器输出信息

try {
client = new Socket("127.0.0.1",8888);//实例化客户端,并与服务器建立连接

input = new BufferedReader(new InputStreamReader(System.in)); //准备读入用户键入信息

out = new PrintStream(client.getOutputStream());//用于向服务器发送请求报文
in = new BufferedReader(new InputStreamReader(client.getInputStream()));//接受服务器响应报文

boolean isEnd = false;
String inputMsg = null ,serverRespMsg = null;
while(!isEnd){
inputMsg = input.readLine(); //从键盘读入用户输入的信息,遇到换行符截止
out.println(inputMsg);//将用户输入的信息发送给服务器
if("bye".equalsIgnoreCase(inputMsg.trim())){
isEnd = true;
} else {
serverRespMsg = in.readLine(); //读取服务器响应报文
System.out.println(serverRespMsg);
}
}

} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
input.close();
in.close();
out.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}


另外,我们可以在服务端加入多线程机制,这样就可以避免以上服务端处理客户端请求时不能并发处理问题

服务端线程处理类:

package com.ray.tcp.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
/**
 * 服务端线程类
 * @author ray
 *
 */
public class EchoServerThread implements Runnable {

private Socket client;
public EchoServerThread(Socket client){
this.client = client;
}

@Override
public void run() {

PrintStream out = null;
BufferedReader in = null;

try {
in = new BufferedReader(new InputStreamReader(this.client.getInputStream()));  //获取客户端输入的数据
out = new PrintStream(this.client.getOutputStream()); //向客户端响应数据

boolean isEnd = false;
while(!isEnd){
String tmp = in.readLine();
System.out.println("client echo: " + tmp);
if(tmp != null && !"bye".equalsIgnoreCase(tmp.trim())){
out.println("server echo: " + tmp);
} else {
isEnd = true;
}
}
in.close(); //关闭客户端输入流
out.close(); //关闭客户端输出流
this.client.close();//与客户端断开连接


} catch (IOException e) {
e.printStackTrace();
}

}


}

服务器接收客户端请求,并启动服务线程,如下:

package com.ray.tcp.demo;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoThreadServer {
public static void main(String[] args) {

ServerSocket server = null;
Socket client = null;

try {
server = new ServerSocket(8888);
while(true){
System.out.println("服务器运行,等待客户端连接...");
client = server.accept();

//启动服务器线程处理类
new Thread(new EchoServerThread(client)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

总结:本章介绍了如何通过java的ServerSocket 和 Socket类的基本使用,并通过示例模拟ECHO程序,带大家对TCP程序的实现有一个初步认识,并通过多线程机制实现服务器多线程处理客户端请求的实现原理,更多网络编程文章待续...

0 0
原创粉丝点击