场景描述:Echo程序是一个网络编程通信交互的一个经典案例,称为“回应程序”。即客户端输入什么内容,服务端就会在这些内容前加上“Echo”\,并将信息发回给客户端。
![](https://img-my.csdn.net/uploads/201210/04/1349359800_6435.png)
![](https://img-my.csdn.net/uploads/201210/04/1349360533_7451.png)
![](https://img-my.csdn.net/uploads/201210/04/1349360556_7991.png)
第一个TCP程序:
建立服务器程序HelloServer.javaimport java.net.* ;
import java.io.* ;
public class HelloServer{
public static void main(String args[]) throws Exception { // 所有异常抛出
ServerSocket server = null ; // 定义ServerSocket类
Socket client = null ; // 表示客 户端
PrintStream out = null ; // 打印流输出最方便
server = new ServerSocket(8888) ; // 服务器在8888端口上监听
System.out.println("服务器运行,等待客户端连接。") ;
client = server.accept() ; // 得到连接,程序进入到阻塞状态
String str = "hello world" ; // 表示要输出的信息
out = new PrintStream(client.getOutputStream()) ;
out.println(str) ; // 向客户端输出信息
client.close() ;
server.close() ;
}
};
程序运行结果:服务器运行,等待客户端连接。
PS:服务器端建立完成后,因为其是以TCP为通信协议的,可以使用tenet命令进行验证,输入“open loaclhost 8888”,即可取得服务器的输出信息。
编写客户端程序HelloCilent.java
import java.net.* ;
import java.io.* ;
public class HelloClient{
public static void main(String args[]) throws Exception { // 所有异常抛出
Socket client = null ; // 表示客 户端
client = new Socket("localhost",8888) ;
BufferedReader buf = null ; // 一次性接收完成
buf = new BufferedReader(new InputStreamReader(client.getInputStream())) ;
String str = buf.readLine() ;
System.out.println("服务器端输出内容:" + str) ;
buf.close() ;
client.close() ;
}
};
程序运行结果(重新打开一个命令行窗口):服务器端输出内容:hello world
Echo程序:
回看之前的Hello程序,服务器每次执行完都会退出,这是因为服务器只能接收一个客户端的连接,主要是由于accept()方法只能使用一次。那么现在让我们循环使用accept()吧!服务器端EchoServer.java
import java.net.* ;
import java.io.* ;
public class EchoServer{
public static void main(String args[]) throws Exception { // 所有异常抛出
ServerSocket server = null ; // 定义ServerSocket类
Socket client = null ; // 表示客 户端
BufferedReader buf = null ; // 接收输入流
PrintStream out = null ; // 打印流输出最方便
server = new ServerSocket(8888) ; // 服务器在8888端口上监听
boolean f = true ; // 定义个标记位
while(f){
System.out.println("服务器运行,等待客户端连接。") ;
client = server.accept() ; // 得到连接,程序进入到阻塞状态
out = new PrintStream(client.getOutputStream()) ;
// 准备接收客户端的输入信息
buf = new BufferedReader(new InputStreamReader(client.getInputStream())) ;
boolean flag = true ; // 标志位,表示可以一直接收并回应信息
while(flag){
String str = buf.readLine() ; // 接收客户端发送的内容
if(str==null||"".equals(str)){ // 表示没有内容
flag = false ; // 退出循环
}else{
if("bye".equals(str)){ // 如果输入的内容为bye表示结束
flag = false ;
}else{
out.println("ECHO : " + str) ; // 回应信息
}
}
}
client.close() ;
}
server.close() ;
}
};
客户端端Echo.java
import java.net.* ;
import java.io.* ;
public class EchoClient{
public static void main(String args[]) throws Exception { // 所有异常抛出
Socket client = null ; // 表示客户端
client = new Socket("localhost",8888) ; // 指定连接主机及端口
BufferedReader buf = null ; // 一次性接收完成
PrintStream out = null ; // 向服务器端发送数据
BufferedReader input = null ;
input = new BufferedReader(
new InputStreamReader(System.in)) ; // 接收键盘数据
buf = new BufferedReader(
new InputStreamReader(
client.getInputStream())) ; // 接收服务器端输入信息
out = new PrintStream(client.getOutputStream()) ;
boolean flag = true ; // 定义标志位
while(flag){ // 不断发送和接收数据
System.out.print("输入信息:") ;
String str = input.readLine() ; // 接收键盘的输入信息
out.println(str) ;
if("bye".equals(str)){ // 如果输入bye表示结束
flag = false ;
}else{
String echo = buf.readLine() ; // 接收返回结果
System.out.println(echo) ; // 输出回应Echo信息
}
}
buf.close() ; // 关闭Socket
client.close() ; // 关闭输入流
}
};
严重问题:即现在服务器端每次只能有一个用户连接,属于单线程的处理机制。
进化:在服务器上应用多线程。
在每一个用户连接之后启动一个新的线程:EchoThread.javaimport java.net.* ;
import java.io.* ;
public class EchoThread implements Runnable{
private Socket client = null ;
public EchoThread(Socket client){
this.client = client ;
}
public void run(){
BufferedReader buf = null ; // 接收输入流
PrintStream out = null ; // 打印流输出最方便
try{
out = new PrintStream(client.getOutputStream()) ;
// 准备接收客户端的输入信息
buf = new BufferedReader(new InputStreamReader(client.getInputStream())) ;
boolean flag = true ; // 标志位,表示可以一直接收并回应信息
while(flag){
String str = buf.readLine() ; // 接收客户端发送的内容
if(str==null||"".equals(str)){ // 表示没有内容
flag = false ; // 退出循环
}else{
if("bye".equals(str)){ // 如果输入的内容为bye表示结束
flag = false ;
}else{
out.println("ECHO : " + str) ; // 回应信息
}
}
}
client.close() ;
}catch(Exception e){}
}
};
编写EchoThreadServer类,并使用以上的EchoThread类:EchoThreadServer.java
import java.net.* ;
import java.io.* ;
public class EchoThreadServer{
public static void main(String args[]) throws Exception { // 所有异常抛出
ServerSocket server = null ; // 定义ServerSocket类
Socket client = null ; // 表示客 户端
server = new ServerSocket(8888) ; // 服务器在8888端口上监听
boolean f = true ; // 定义个标记位
while(f){
System.out.println("服务器运行,等待客户端连接。") ;
client = server.accept() ; // 得到连接,程序进入到阻塞状态
new Thread(new EchoThread(client)).start() ; // 每一个客户端表示一个线程
}
server.close() ;
}
};