下面简单通过一个TCP客户端及服务端程序,来模拟我们常用的telnet程序的回应功能,即客户端输入哪些内容,服务端经过简单字符串处理进行响应。
简介:在java中使用Socket,即套接字完成TCP程序的开发,使用此类与服务器建立可靠,双向,持续,点对点的通信连接,在socket程序开发中,服务端使用serversocket等待客户端连接,而所有客户端通过socket对象与服务端建立连接,下边简单列出ServerSocket 与 socket常用API:
ServerSocket:
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程序的实现有一个初步认识,并通过多线程机制实现服务器多线程处理客户端请求的实现原理,更多网络编程文章待续...