Server
package com.cloud.test4;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 商业的服务器
* 1、多线程 thread
* 1)一个客户端启动一个线程为之服务
* 2)主线程监听客户端的请求
* 2、线程池 threadPool
* 1)控制线程的数量,提升Server的伸缩性
* 2)减少线程创建的开销
* 3、缓冲队列 blockingQueue
* 1)不要让客户端线程直接访问文件,数据库等资源
* 2)通过队列来做缓冲(客户端线程将数据放入队列中,让专门的线程负责将队列中的数据放入文件或者数据库中)
* 3)队列必须可以是线程安全的,一般队列有阻塞的功能
* 4、封装好协议
*/
public class ServerDemo {
private ServerSocket ss;
private int online;// 连接的客户端数量
private ExecutorService threadPool;// 线程池
private BlockingQueue queue;
private String fileName;// 文件存储地址
public ServerDemo() throws IOException {
online = 0;
fileName = "e:/file.txt";
// 设置服务器端口
ss = new ServerSocket(8899);
// 创建指定线程数量的线程池
threadPool = Executors.newFixedThreadPool(100);
queue = new LinkedBlockingQueue(1000);
}
public void start() throws IOException {
SaveThread saveThread = new SaveThread();
// 有未做完的任务,所以不设置成守护线程
saveThread.start();
// 连接线程 定时显示正在连接的客户端数量
OnlineThread onlineThread = new OnlineThread();
onlineThread.setDaemon(true);
onlineThread.start();
while (true) {
// 等待接收客户端发送过来的请求
Socket socket = ss.accept();
// 实现了runnable接口的内部类
Handler handler = new Handler(socket);
// 线程池中的线程启动runnable中的run方法
threadPool.execute(handler);
}
}
// 实现runnable接口的类 因为线程已经创建 所以不再继承Thread类
class Handler implements Runnable {
private Socket socket;
Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
incOnline();
// 对话中获取输入输出流
InputStream is = socket.getInputStream();// 听
OutputStream os = socket.getOutputStream();// 说
OutputStreamWriter osw = new OutputStreamWriter(os);
PrintWriter pw = new PrintWriter(osw);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
// 先读取客户端发送过来的请求,再发送信息回去
String line = br.readLine();
boolean b = offer(line);
if (b) {
pw.print("ok");// 给客户端响应信号
} else {
pw.println("error");
}
// 自身封装缓冲,所以调用flush方法
pw.flush();
} catch (Exception e) {
System.out.println("网络异常");
} finally {
if (socket != null)
try {
socket.close();
decOnline();
} catch (IOException e) {
}
}
}
}
public synchronized void incOnline() {
online++;
}
public synchronized void decOnline() {
online--;
}
public synchronized int getOnline() {
return online;
}
// 开启一个线程 记录当前与服务器连接的客户端数量
private class OnlineThread extends Thread {
public void run() {
while (true) {
try {
System.out.println("online : " + getOnline());
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}
}
// 将字符串存入缓冲队列中
private boolean offer(String str) {
boolean b = false;
try {
b = queue.offer(str, 5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
return b;
}
// 取出缓冲队列中的字符串
private String poll() {
String line = null;
try {
line = queue.poll(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
return line;
}
private class SaveThread extends Thread {
@Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
String line = null;
FileOutputStream fos = new FileOutputStream(fileName, true);
OutputStreamWriter osw = new OutputStreamWriter(fos);
while ((line = poll()) != null) {
osw.write(line);
}
osw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
System.out.println("server");
ServerDemo sd = new ServerDemo();
sd.start();
}
}
Client
package com.cloud.test4;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientDemo {
public void request()throws Exception{
//客户端 设置连接的服务器的位置
Socket socket = new Socket("localhost",8899);//IP地址 端口号
InputStream is = socket.getInputStream();//听
OutputStream os = socket.getOutputStream();//说
OutputStreamWriter osw = new OutputStreamWriter(os);
PrintWriter pw = new PrintWriter(osw);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//发送控制台中的信息
Scanner scanner = new Scanner(System.in);
String line = scanner.next();
pw.println(line);
pw.flush();//内部自带缓冲
String str = br.readLine();
if("ok".equals(str)){
System.out.println("发送成功");
}else{
System.out.println("发送失败");
}
socket.close();
}
public static void main(String[] args)throws Exception {
System.out.println("client");
ClientDemo cd = new ClientDemo();
cd.request();
}
}