基于线程池的http服务器
2016-07-05 11:18
295 查看
前端时间,用线程池做了一个http服务器,专门处理get请求,基于socket编程,主要是自己想对操作系统级的编程比较感兴趣。好了,贴出代码,供大家参考:
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
ServerSocket server = new ServerSocket(8000);
System.out.println("Server is listenning");
ThreadPoolManager manager = new ThreadPoolManager(3);
int i = 0;
while(true){
Socket client = server.accept();
manager.add(client);
i++;
System.out.println(i);
}
}catch(IOException e){
e.printStackTrace();
}
}
这是整个程序的入口,初始化该初始化的,监听该
监听的。ThreadPoolManager用于管理线程,初始化有三个线程。
accept方法会造成阻塞,知道有消息传过来。将接收到的消息传入到manager中以便于管理。
线程池类,线程池在初始化之后放入一个vector之中,同时将请求放入一个缓冲区中,缓冲区用 ArrayBlockingQueue来做。
BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。ArrayBlockingQueue是对BlockingQueue的一个数组实现,它使用一把全局的锁并行对queue的读写操作,同时使用两个Condition阻塞容量为空时的取操作和容量满时的写操作。
public synchronized void run(){
try{
while(true){
synchronized (buffer) {
if(buffer.isEmpty()){
buffer.wait();
}
this.client = buffer.poll();
System.out.println(this.number+"------running");
}
PrintStream outStream;
BufferedReader in ;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
outStream = new PrintStream(new BufferedOutputStream(client.getOutputStream()));
this.argument=in.readLine();
if(getRequest(this.argument)){
String fileName = getFileName(this.argument);
File file = new File(fileName);
if(file.exists()){
sendFile(outStream,file);
}else
System.out.println("不存在图片");
}
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sleep(3*1000);
//System.out.println("Thread is sleeping");
}
}catch(InterruptedException e){
System.out.println("Interrupt");
}
}
不断监视缓冲区中的动向,如果有了数据,就从缓冲区中取出socket,否则进入等待列,将socket封装到bufferReader中,取出请求的报文头,如果请求的文件存在,就将文件放入PrintStream中,送入客户端。为了看出效果,让线程工作完之后睡3秒钟。
通过截取报文头,来获取请求文件的位置。
将流传输到客户端的过程,先将数据写入到一个字节流中,输入到客户端。
这样,一个简单的http服务器就完成了,服务器还有一个问题,就是请求过来之后会阻塞。从高人处得知,可以用nio这种非阻塞的io进行优化。正在研究之中。
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
ServerSocket server = new ServerSocket(8000);
System.out.println("Server is listenning");
ThreadPoolManager manager = new ThreadPoolManager(3);
int i = 0;
while(true){
Socket client = server.accept();
manager.add(client);
i++;
System.out.println(i);
}
}catch(IOException e){
e.printStackTrace();
}
}
这是整个程序的入口,初始化该初始化的,监听该
监听的。ThreadPoolManager用于管理线程,初始化有三个线程。
accept方法会造成阻塞,知道有消息传过来。将接收到的消息传入到manager中以便于管理。
public class ThreadPoolManager { private int maxThread; public Vector<SimpleThreak> vector; public Queue<Socket> buffer; public void setMaxThread(int maxThread) { this.maxThread = maxThread; } public int getMaxThread() { return maxThread; } public ThreadPoolManager(int threadCount){ this.setMaxThread(threadCount); buffer = new ArrayBlockingQueue<Socket>(100); System.out.println("Starting pool"); vector = new Vector<SimpleThreak>(); for(int i=1;i<=threadCount;i++){ SimpleThreak st = new SimpleThreak(i,buffer); vector.add(st); st.start(); } } public void add(Socket client){ synchronized (buffer) { buffer.offer(client); buffer.notify(); } }
线程池类,线程池在初始化之后放入一个vector之中,同时将请求放入一个缓冲区中,缓冲区用 ArrayBlockingQueue来做。
BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。ArrayBlockingQueue是对BlockingQueue的一个数组实现,它使用一把全局的锁并行对queue的读写操作,同时使用两个Condition阻塞容量为空时的取操作和容量满时的写操作。
public synchronized void run(){
try{
while(true){
synchronized (buffer) {
if(buffer.isEmpty()){
buffer.wait();
}
this.client = buffer.poll();
System.out.println(this.number+"------running");
}
PrintStream outStream;
BufferedReader in ;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
outStream = new PrintStream(new BufferedOutputStream(client.getOutputStream()));
this.argument=in.readLine();
if(getRequest(this.argument)){
String fileName = getFileName(this.argument);
File file = new File(fileName);
if(file.exists()){
sendFile(outStream,file);
}else
System.out.println("不存在图片");
}
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sleep(3*1000);
//System.out.println("Thread is sleeping");
}
}catch(InterruptedException e){
System.out.println("Interrupt");
}
}
不断监视缓冲区中的动向,如果有了数据,就从缓冲区中取出socket,否则进入等待列,将socket封装到bufferReader中,取出请求的报文头,如果请求的文件存在,就将文件放入PrintStream中,送入客户端。为了看出效果,让线程工作完之后睡3秒钟。
private String getFileName(String s){ String f = s.substring(s.indexOf(' ')+1); f=f.substring(0,f.indexOf(' ')); try{ if(f.charAt(0)=='/') f=f.substring(1); }catch(StringIndexOutOfBoundsException e){ e.printStackTrace(); } if(f.equals("")) f = "index.html"; return f; }
通过截取报文头,来获取请求文件的位置。
private void sendFile(PrintStream ps,File file){ try{ DataInputStream ds = new DataInputStream(new FileInputStream(file)); int len = (int) file.length(); //System.out.println(len); byte buf[]=new byte[len]; ds.readFully(buf); ps.write(okResponse().getBytes()); ps.write(buf,0,len); ps.flush(); ds.close(); }catch(Exception e){ e.printStackTrace(); } }
将流传输到客户端的过程,先将数据写入到一个字节流中,输入到客户端。
这样,一个简单的http服务器就完成了,服务器还有一个问题,就是请求过来之后会阻塞。从高人处得知,可以用nio这种非阻塞的io进行优化。正在研究之中。
相关文章推荐
- OSI七层协议和TCP/IP四层协议之比较
- linux C 网络编程基础
- 读书笔记-java网络编程-5URL和URI-URI类
- cordova支持私人HTTPS证书
- httpclient post
- 【Netty4.X】Unity客户端与Netty服务器的网络通信(一)
- uefi与win8 (根据网络资料整理)
- python学习:编写TCP服务器&UDP服务器
- 【百宝云网络验证】—易语言开发的系统
- 通信网络基础总结
- mysql-5.7.5-labs-http-documentation中文翻译-第三章 安装
- eclipse Exception in thread "http-bio-8080-exec-2" java.lang.OutOfMemoryError: PermGen space
- Java网络编程中inputStream.available()的使用方法
- Java网络编程socket
- 网络共享打印机只能打印第一页问题解决
- 网络参考模型
- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- 深入理解HTTP Session
- HTTP基础:URL格式、 HTTP请求、响应、消息
- WebSocket 是什么原理?为什么可以实现持久连接?