基于线程池的http服务器

     前端时间,用线程池做了一个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进行优化。正在研究之中。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值