您的位置:首页 > 理论基础 > 计算机网络

基于线程池的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中以便于管理。

   

 

 

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进行优化。正在研究之中。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: