使用ExecutorService实现线程池,详细要求如下:
1) 线程池要执行的任务为每隔一秒输出一次当前线程的名字,总计输出10次。
2) 创建一个线程池,该线程池中只有两个空线程。
3) 使线程池执行5次步骤一的任务。
实现此案例需要按照如下步骤进行。
步骤一:创建类
首先,创建名为TestExecutorService的类;然后,在该类相同的文件中创建名为Handler的类,该类实现了Runnable接口,是线程池要执行的任务,代码如下所示:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 测试线程池 */ public class TestExecutorService { public static void main(String[] args) { } } class Handler implements Runnable{ public void run(){ } }
步骤二:覆盖run方法
在Handler类中覆盖run方法,在该方法中实现每隔一秒输出一次当前线程的名字,总计输出10次,代码如下所示:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 测试线程池 */ public class TestExecutorService { public static void main(String[] args) { } } class Handler implements Runnable{ public void run(){ #cold_bold String name = Thread.currentThread().getName(); #cold_bold System.out.println("执行当前任务的线程为:"+name); #cold_bold for(int i=0;i<10;i++){ #cold_bold System.out.println(name+":"+i); #cold_bold try { #cold_bold Thread.sleep(1000); #cold_bold } catch (InterruptedException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold System.out.println(name+":任务完毕"); } }
步骤三:创建线程池
使用Executors类的静态方法newFixedThreadPool,创建一个包含两个空线程的线程池,代码如下所示:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 测试线程池 */ public class TestExecutorService { public static void main(String[] args) { #cold_bold ExecutorService threadPool = Executors.newFixedThreadPool(2); } } class Handler implements Runnable{ public void run(){ String name = Thread.currentThread().getName(); System.out.println("执行当前任务的线程为:"+name); for(int i=0;i<10;i++){ System.out.println(name+":"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(name+":任务完毕"); } }
步骤四:设置线程池要执行的任务
使用ExecutorService类的execute方法设置线程池要执行的任务,在此线程池要执行的任务即为Handler类中创建的任务;另外,要执行5次该任务,那么循环5次即可,代码如下所示:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 测试线程池 */ public class TestExecutorService { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(2); #cold_bold for(int i=0;i<5;i++){ #cold_bold Handler handler = new Handler(); #cold_bold threadPool.execute(handler); #cold_bold } } } class Handler implements Runnable{ public void run(){ String name = Thread.currentThread().getName(); System.out.println("执行当前任务的线程为:"+name); for(int i=0;i<10;i++){ System.out.println(name+":"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(name+":任务完毕"); } }
运行上述代码,控制台输出的结果如下:
执行当前任务的线程为:pool-1-thread-1 执行当前任务的线程为:pool-1-thread-2 pool-1-thread-2:0 pool-1-thread-1:0 pool-1-thread-1:1 pool-1-thread-2:1 pool-1-thread-1:2 pool-1-thread-2:2 pool-1-thread-2:3 pool-1-thread-1:3 pool-1-thread-2:4 pool-1-thread-1:4 pool-1-thread-1:5 pool-1-thread-2:5 pool-1-thread-1:6 pool-1-thread-2:6 pool-1-thread-1:7 pool-1-thread-2:7 pool-1-thread-2:8 pool-1-thread-1:8 pool-1-thread-2:9 pool-1-thread-1:9 pool-1-thread-1:任务完毕 执行当前任务的线程为:pool-1-thread-1 pool-1-thread-1:0 pool-1-thread-2:任务完毕 执行当前任务的线程为:pool-1-thread-2 pool-1-thread-2:0 pool-1-thread-1:1 pool-1-thread-2:1 pool-1-thread-1:2 pool-1-thread-2:2 pool-1-thread-1:3 pool-1-thread-2:3 pool-1-thread-1:4 pool-1-thread-2:4 pool-1-thread-1:5 pool-1-thread-2:5 pool-1-thread-1:6 pool-1-thread-2:6 pool-1-thread-1:7 pool-1-thread-2:7 pool-1-thread-1:8 pool-1-thread-2:8 pool-1-thread-1:9 pool-1-thread-2:9 pool-1-thread-1:任务完毕 执行当前任务的线程为:pool-1-thread-1 pool-1-thread-1:0 pool-1-thread-2:任务完毕 pool-1-thread-1:1 pool-1-thread-1:2 pool-1-thread-1:3 pool-1-thread-1:4 pool-1-thread-1:5 pool-1-thread-1:6 pool-1-thread-1:7 pool-1-thread-1:8 pool-1-thread-1:9 pool-1-thread-1:任务完毕
从输出结果可以看出,线程池每次启动两个线程来执行任务。由于要求执行5次任务,所以线程池分三次执行,前两次各执行2个任务,最后一次执行一个任务。
本案例中,类TestExecutorService的完整代码如下所示:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 测试线程池 */ public class TestExecutorService { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(2); for(int i=0;i<5;i++){ Handler handler = new Handler(); threadPool.execute(handler); } } } class Handler implements Runnable{ public void run(){ String name = Thread.currentThread().getName(); System.out.println("执行当前任务的线程为:"+name); for(int i=0;i<10;i++){ System.out.println(name+":"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(name+":任务完毕"); } }
测试BlockingQueue的使用,详细要求如下:
1) 首先,使用ArrayBlockingQueue类创建一个大小为10的双缓冲队列queue;然后,循环20次向队列queue中添加元素,如果5秒内元素仍没有入队到队列中,则返回false。
2) 首先,使用ArrayBlockingQueue类创建一个大小为10的双缓冲队列queue;然后,将0到9,10个数字加入到队列queue中;最后,循环20次从队列queue中取元素,如果5秒内还没有元素可取出则返回null。
实现此案例需要按照如下步骤进行。
步骤一:创建双缓冲队列
首先,创建TestBlockingQueue类;然后在该类中添加测试方法testOffer;最后,
使用ArrayBlockingQueue类创建一个大小为10的双缓冲队列queue,代码如下所示:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * 测试双缓冲队列 */ public class TestBlockingQueue { /** * 测试入队方法 */ @Test public void testOffer() { BlockingQueue <Integer> queue = new ArrayBlockingQueue<Integer>(10); } }
步骤二:测试offer方法
使用双缓冲队列BlockingQueue的offer方法向队列queue中添加元素,代码如下所示:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * 测试双缓冲队列 */ public class TestBlockingQueue { /** * 测试入队方法 */ @Test public void testOffer() { BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); #cold_bold for(int i=0;i<20;i++){ #cold_bold try { #cold_bold //设置5秒超时,5秒内元素仍没有入队到队列中,则返回false #cold_bold boolean b = queue.offer(i,5,TimeUnit.SECONDS); #cold_bold System.out.println("存入是否成功:"+b); #cold_bold } catch (InterruptedException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } } }
上述代码中的offer方法的三个参数分别表示入队元素、超时时长以及超时的时间单位。
运行上述代码,控制台输出结果如下所示:
存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:true 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false 存入是否成功:false
从输出结果可以看出,输出了10次“存入是否成功:true”、10次“存入是否成功:false”,这是因为双缓冲队列的大小为10,入队10个元素后,则不能再有元素入队了。
步骤三:创建测试方法testPull
首先在TestBlockingQueue类中添加测试方法testPull;然后,使用ArrayBlockingQueue类创建一个大小为10的双缓冲队列queue,代码如下所示:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * 测试双缓冲队列 */ public class TestBlockingQueue { /** * 测试入队方法 */ @Test public void testOffer() { BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); for(int i=0;i<20;i++){ try { //设置5秒超时,5秒内元素仍没有入队到队列中,则返回false boolean b = queue.offer(i,5,TimeUnit.SECONDS); System.out.println("存入是否成功:"+b); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 测试出队方法 */ #cold_bold @Test #cold_bold public void testPull() { #cold_bold BlockingQueue<Integer> queue #cold_bold = new ArrayBlockingQueue<Integer>(10); #cold_bold } }
步骤四:测试poll方法
首先,使0到9,10个数字加入到队列queue中;然后,使用双缓冲队列BlockingQueue的poll方法使queue中的元素出队,如果5秒内还没有元素可取出则返回null,代码如下所示:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * 测试双缓冲队列 */ public class TestBlockingQueue { /** * 测试入队方法 */ @Test public void testOffer() { BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); for(int i=0;i<20;i++){ try { //设置5秒超时,5秒内元素仍没有入队到队列中,则返回false boolean b = queue.offer(i,5,TimeUnit.SECONDS); System.out.println("存入是否成功:"+b); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 测试出队方法 */ @Test public void testPull() { BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); #cold_bold for(int i=0;i<10;i++){ #cold_bold queue.offer(i); #cold_bold } #cold_bold for(int i =0;i<20;i++){ #cold_bold //获取元素,设置5秒超时,5秒内还没有元素可取出则返回null #cold_bold try { #cold_bold Integer num = queue.poll(5, TimeUnit.SECONDS); #cold_bold System.out.println("元素:"+num); #cold_bold } catch (InterruptedException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } } }
运行上述代码,控制台输出的结果如下所示:
元素:0 元素:1 元素:2 元素:3 元素:4 元素:5 元素:6 元素:7 元素:8 元素:9 元素:null 元素:null 元素:null 元素:null 元素:null 元素:null 元素:null 元素:null 元素:null 元素:null
从输出结果可以看出,输出了10次“元素:+数字”、10次“元素:null”,这是因为双缓冲队列中只有10个元素,全部取出后,再取则返回null。
本案例中,类TestBlockingQueue的完整代码如下所示:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * 测试双缓冲队列 */ public class TestBlockingQueue { /** * 测试入队方法 */ @Test public void testOffer() { BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); for(int i=0;i<20;i++){ try { //设置5秒超时,5秒内元素仍没有入队,则返回false boolean b = queue.offer(i,5,TimeUnit.SECONDS); System.out.println("存入是否成功:"+b); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 测试出队方法 */ @Test public void testPull() { BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10); for(int i=0;i<10;i++){ queue.offer(i); } for(int i =0;i<20;i++){ //获取元素,设置5秒超时,5秒内还没有元素可取出则返回null try { Integer num = queue.poll(5, TimeUnit.SECONDS); System.out.println("元素:"+num); } catch (InterruptedException e) { e.printStackTrace(); } } } }
使用Java的Socket实现客户端和服务器端之间的连接,并使客户端向服务端发送一条消息。
通信过程如表-1所示:
表- 1 客户端与服务器端通信过程
实现此案例需要按照如下步骤进行。
步骤一:创建客户端类
新建名为com.tarena.part1的包,并在包下新建名为Client的类,用于表示客户端,代码如下所示:
package com.tarena.part1; /** * 客户端应用程序 * 第一步:实现向服务器发送一条信息 */ public class Client { }
步骤二:创建Socket类的对象
在Client 类中声明全局变量 socket 表示一个客户端Socket对象,并在实例化 Client 类时使用构造方法“Socket(String ip,int port)”来创建Socket类的对象。此时,需要进行异常处理。代码如下所示:
package com.tarena.part1; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; /** * 客户端应用程序 * 第一步:实现向服务器发送一条信息 */ public class Client { //客户端Socket #cold_bold private Socket socket; /** * 构造方法,用于初始化 */ #cold_bold public Client(){ #cold_bold try { #cold_bold socket = new Socket("localhost",8088); #cold_bold } catch (Exception e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } }
步骤三:创建客户端工作方法 start()
创建客户端工作方法 start(),并添加代码实现连接服务器端并发送信息。
首先使用Socket类的getOutputStream方法获取对应Socket对象的网络字节输出流对象;然后,为了写出数据,构造缓冲字符输出流PrintWriter类的对象,使用该对象的println方法向服务器发送数据。
注意,这里需要进行异常处理,并在 finally 语句中,关闭 Socket 对象。
Client 类的代码如下所示:
package com.tarena.part1; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; /** * 客户端应用程序 * 第一步:实现向服务器发送一条信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } /** * 客户端工作方法 */ #cold_bold public void start(){ #cold_bold try { #cold_bold OutputStream out = socket.getOutputStream(); #cold_bold OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); #cold_bold PrintWriter pw = new PrintWriter(osw,true); #cold_bold pw.println("你好!服务器"); #cold_bold } catch (Exception e) { #cold_bold e.printStackTrace(); #cold_bold } finally{ #cold_bold if(socket != null){ #cold_bold try { #cold_bold socket.close(); #cold_bold } catch (IOException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold } #cold_bold } }
步骤四:为客户端类定义 main() 方法
为类 Client 定义 main() 方法,并在 main() 方法中,创建 Client 对象,调用上一步中所创建的 start() 方法。代码如下所示:
package com.tarena.part1; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; /** * 客户端应用程序 * 第一步:实现向服务器发送一条信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } /** * 客户端工作方法 */ public void start(){ try { OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); PrintWriter pw = new PrintWriter(osw,true); pw.println("你好!服务器"); } catch (Exception e) { e.printStackTrace(); } finally{ if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } #cold_bold public static void main(String[] args) { #cold_bold Client client = new Client(); #cold_bold client.start(); #cold_bold } }
步骤五:创建服务器端类
新建名为Server的类,用于表示服务器端,代码如下所示:
package com.tarena.part1; /** * 服务端应用程序 */ public class Server { }
步骤六:创建ServerSocket类的对象
在Server 类中声明全局变量 serverSocket 表示一个服务器端ServerSocket对象,并在实例化 Server 类时使用构造方法“ServerSocket(int port)”来创建对象。此时,需要进行异常处理。代码如下所示:
package com.tarena.part1; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket #cold_bold private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ #cold_bold public Server(){ #cold_bold try { #cold_bold serverSocket = new ServerSocket(8088); #cold_bold } catch (Exception e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } }
步骤七:创建服务器端工作方法 start()
创建服务器端工作方法 start(),用于读取客户端发来的信息。
首先监听客户端的连接,得到Socket 对象,并使用Socket类的getInputStream方法获取对应Socket对象的网络字节输入流对象;然后,为了读取数据,构造缓冲字符输入流BufferedReader类的对象,并调用该对象的 readLine 方法获取客户端发来的数据。
注意,这里需要进行异常处理,并在 finally 语句中,关闭 Socket 对象。
Server 类的代码如下所示:
package com.tarena.part1; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } /** * 服务端开启方法 */ #cold_bold public void start(){ #cold_bold try { #cold_bold System.out.println("等待客户端连接..."); #cold_bold //监听客户端的连接 #cold_bold Socket socket = serverSocket.accept(); #cold_bold System.out.println("客户端已连接!"); #cold_bold InputStream in = socket.getInputStream(); #cold_bold InputStreamReader isr = new InputStreamReader(in,"UTF-8"); #cold_bold BufferedReader br = new BufferedReader(isr); #cold_bold System.out.println("客户端说:"+br.readLine()); #cold_bold } catch (Exception e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } }
步骤八:为服务器端类定义 main 方法
为类 Server 定义 main 方法,并在 main 方法中,创建 Server 对象,调用上一步中所创建的 start 方法。代码如下所示:
package com.tarena.part1; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } /** * 服务端开启方法 */ public void start(){ try { System.out.println("等待客户端连接..."); //监听客户端的连接 Socket socket = serverSocket.accept(); System.out.println("客户端已连接!"); InputStream in = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(in,"UTF-8"); BufferedReader br = new BufferedReader(isr); System.out.println("客户端说:"+br.readLine()); } catch (Exception e) { e.printStackTrace(); } } #cold_bold public static void main(String[] args) { #cold_bold Server server = new Server(); #cold_bold server.start(); #cold_bold } }
步骤九:测试
首先,启动服务器端;然后再启动客户端。
服务器端控制台运行输出如下:
等待客户端连接... 客户端已连接! 客户端说:你好!服务器
本案例中,Client类的完整代码如下所示:
package com.tarena.part1; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; /** * 客户端应用程序 * 第一步:实现向服务器发送一条信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } /** * 客户端工作方法 */ public void start(){ try { OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); PrintWriter pw = new PrintWriter(osw,true); pw.println("你好!服务器"); } catch (Exception e) { e.printStackTrace(); } finally{ if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Client client = new Client(); client.start(); } }
Server类的完整代码如下所示:
package com.tarena.part1; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } /** * 服务端开启方法 */ public void start(){ try { System.out.println("等待客户端连接..."); //监听客户端的连接 Socket socket = serverSocket.accept(); System.out.println("客户端已连接!"); InputStream in = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(in,"UTF-8"); BufferedReader br = new BufferedReader(isr); System.out.println("客户端说:"+br.readLine()); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { Server server = new Server(); server.start(); } }
改善聊天室案例V1,实现客户端重复发送数据到服务器端的功能。即,用户可以在控制台不断输入内容,并将内容逐一发送给服务端。
此案例在上一个案例的基础上修改部分功能即可。
首先,对于客户端而言,为了能够重复发送信息,需要构建循环,并在循环中,不断读入控制台录入的数据并发送。代码如下所示:
//创建Scanner读取用户输入内容 Scanner scanner = new Scanner(System.in); while(true){ //pw 为PrintWriter 对象 pw.println(scanner.nextLine()); }
其次,对于服务器端,也需要构建循环,并在循环中不断读取客户端发来的数据并打印显示。代码如下所示:
//循环读取客户端发送的信息 while(true){ //br 为BufferedReader 对象 System.out.println("客户端说:"+br.readLine()); }
实现此案例需要按照如下步骤进行。
步骤一:创建客户端类
新建名为com.tarena.part2的包,并在包下新建名为Client的类,用于表示客户端。在Client 类中声明全局变量 socket 表示一个客户端Socket对象,并在实例化 Client 类时创建Socket类的对象。代码如下所示:
package com.tarena.part2; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; /** * 客户端应用程序 * 第二步:实现向服务器循环发送信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } }
步骤二:创建客户端工作方法 start()
创建客户端工作方法 start(),并添加代码实现连接服务器端并发送信息。为了能够重复发送信息,需要构建循环,并在循环中,不断读入控制台录入的数据并发送。
Client 类的代码如下所示:
package com.tarena.part2; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; /** * 客户端应用程序 * 第二步:实现向服务器循环发送信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } /** * 客户端工作方法 */ #cold_bold public void start(){ #cold_bold try { #cold_bold OutputStream out = socket.getOutputStream(); #cold_bold OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); #cold_bold PrintWriter pw = new PrintWriter(osw,true); #cold_bold #cold_bold //创建Scanner读取用户输入内容 #cold_bold Scanner scanner = new Scanner(System.in); #cold_bold while(true){ #cold_bold pw.println(scanner.nextLine()); #cold_bold } #cold_bold } catch (Exception e) { #cold_bold e.printStackTrace(); #cold_bold } finally{ #cold_bold if(socket != null){ #cold_bold try { #cold_bold socket.close(); #cold_bold } catch (IOException e) { #cold_bold e.printStackTrace(); #cold_bold } #cold_bold } #cold_bold } #cold_bold } }
步骤三:为客户端类定义 main() 方法
为类 Client 定义 main() 方法,并在 main() 方法中,创建 Client 对象,调用上一步中所创建的 start() 方法。代码如下所示:
package com.tarena.part2; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; /** * 客户端应用程序 * 第二步:实现向服务器循环发送信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } /** * 客户端工作方法 */ public void start(){ try { OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); PrintWriter pw = new PrintWriter(osw,true); //创建Scanner读取用户输入内容 Scanner scanner = new Scanner(System.in); while(true){ pw.println(scanner.nextLine()); } } catch (Exception e) { e.printStackTrace(); } finally{ if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } #cold_bold public static void main(String[] args) { #cold_bold Client client = new Client(); #cold_bold client.start(); #cold_bold } }
步骤四:创建服务器端类
新建名为Server的类,用于表示服务器端,并在Server 类中声明全局变量 serverSocket 表示一个服务器端ServerSocket对象,并在实例化 Server 类时创建该对象。此时,需要进行异常处理。代码如下所示:
package com.tarena.part2; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } }
步骤五:创建服务器端工作方法 start()
创建服务器端工作方法 start(),用于读取客户端发来的信息。需要构建循环,并在循环中不断读取客户端发来的数据并打印显示。
Server 类的代码如下所示:
package com.tarena.part2; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } /** * 服务端开启方法 */ public void start(){ #cold_bold try { #cold_bold System.out.println("等待客户端连接..."); #cold_bold //监听客户端的连接 #cold_bold Socket socket = serverSocket.accept(); #cold_bold System.out.println("客户端已连接!"); #cold_bold InputStream in = socket.getInputStream(); #cold_bold InputStreamReader isr = new InputStreamReader(in,"UTF-8"); #cold_bold BufferedReader br = new BufferedReader(isr); #cold_bold #cold_bold //循环读取客户端发送的信息 #cold_bold while(true){ #cold_bold System.out.println("客户端说:"+br.readLine()); #cold_bold } #cold_bold } catch (Exception e) { #cold_bold e.printStackTrace(); #cold_bold } } }
步骤六:为服务器端类定义 main 方法
为类 Server 定义 main 方法,并在 main 方法中,创建 Server 对象,调用上一步中所创建的 start 方法。代码如下所示:
package com.tarena.part2; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } /** * 服务端开启方法 */ public void start(){ try { System.out.println("等待客户端连接..."); //监听客户端的连接 Socket socket = serverSocket.accept(); System.out.println("客户端已连接!"); InputStream in = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(in,"UTF-8"); BufferedReader br = new BufferedReader(isr); //循环读取客户端发送的信息 while(true){ System.out.println("客户端说:"+br.readLine()); } } catch (Exception e) { e.printStackTrace(); } } #cold_bold public static void main(String[] args) { #cold_bold Server server = new Server(); #cold_bold server.start(); #cold_bold } }
步骤七:测试
首先,启动服务器端。此时,服务器端将等待客户端的连接和数据发送。服务器端控制台输出如图-1所示:
图-1
然后再启动客户端,并在客户端重复输入文本后回车。界面效果如图-2所示:
图-2
查看服务器端的控制台输出,界面效果如图-3所示:
图-3
本案例中,Client类的完整代码如下所示:
package com.tarena.part2; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; /** * 客户端应用程序 * 第二步:实现向服务器循环发送信息 */ public class Client { //客户端Socket private Socket socket; /** * 构造方法,用于初始化 */ public Client(){ try { socket = new Socket("localhost",8088); } catch (Exception e) { e.printStackTrace(); } } /** * 客户端工作方法 */ public void start(){ try { OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); PrintWriter pw = new PrintWriter(osw,true); //创建Scanner读取用户输入内容 Scanner scanner = new Scanner(System.in); while(true){ pw.println(scanner.nextLine()); } } catch (Exception e) { e.printStackTrace(); } finally{ if(socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Client client = new Client(); client.start(); } }
Server类的完整代码如下所示:
package com.tarena.part2; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务端应用程序 */ public class Server { //服务端Socket private ServerSocket serverSocket; /** * 构造方法,用于初始化 */ public Server(){ try { serverSocket = new ServerSocket(8088); } catch (Exception e) { e.printStackTrace(); } } /** * 服务端开启方法 */ public void start(){ try { System.out.println("等待客户端连接..."); //监听客户端的连接 Socket socket = serverSocket.accept(); System.out.println("客户端已连接!"); InputStream in = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(in,"UTF-8"); BufferedReader br = new BufferedReader(isr); //循环读取客户端发送的信息 while(true){ System.out.println("客户端说:"+br.readLine()); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { Server server = new Server(); server.start(); } }