socket编程(三)--服务器端实现多线程处理客户端请求并且将客户请求放在连接池中...

需求:通socket编程(一)的需求

该实例中,客户端可能会有多个,服务器的处理器也会有多个,该情形类似于消费者在超市结账的过程,

假设固定有5个收银员,而消费者不确定:

如果开始没有消费者来结账,那么所有的收银员都处于等待状态;

如果有一个消费者来结账,那么随即会有一个收银员来处理,其他的收银员仍处于等待状态;

如果有大于一个小于6个的消费者来结账,那么收银员都会随即进行处理;

如果有大于5个的消费者在等待,就需要排队了(这也就是要说的连接池即客户端的请求链接放置的地方,把客户请求放在这个池子里)

 

客户端:

package com.socket.clientsocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Sclient {

	/**
	 * @param args
	 */
	
	protected BufferedReader socketReader;
	protected PrintWriter socketWriter;
	protected String hostIp;
	protected int hostPort;
	
	
	public Sclient(String ahostIp,int ahostPort){
		this.hostIp = ahostIp;
		this.hostPort = ahostPort;
		
	}
	public void setUpConnection(){
	
		try {
			//1.创建Socket,建立连接
			Socket socket = new Socket(hostIp,hostPort);
			//2.获取输入流和输出流,并进行封装
			socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			socketWriter = new PrintWriter(socket.getOutputStream());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public void tearDownConnection(){
		
		try {
			socketReader.close();
			socketWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}
	//根据需求,对流进行处理
	public String getFile(String fileNameToGet){
		StringBuffer sb = new StringBuffer();
		socketWriter.println(fileNameToGet);
		socketWriter.flush();
		String line = null;
		try {
			while((line = socketReader.readLine()) != null){
				sb = sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}
	public static void main(String[] args) {
		//创建客户端
		Sclient client = new Sclient("198.27.0.166",8200);
		//建立连接
		client.setUpConnection();
		//需求操作
		String content = client.getFile("c:\\log.txt");
		//关闭连接
		client.tearDownConnection();
	}

}

 服务器端:

package com.socket.poolSocketServer;

import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;

public class PooledRemoteFileServer {

	/**
	 * @param args
	 */
	protected int maxConnections;
    protected int listenPort;
    protected ServerSocket serverSocket;
    public PooledRemoteFileServer(int aListenPort, int maxConnections) {
        listenPort = aListenPort;
        this.maxConnections = maxConnections;
    }
    public void acceptConnections() {
        try {
            ServerSocket server = new ServerSocket(listenPort, 5);
            Socket incomingConnection = null;
            while (true) {
                incomingConnection = server.accept();
                handleConnection(incomingConnection);
            }
        } catch (BindException e) {
            System.out.println("Unable to bind to port " + listenPort);
        } catch (IOException e) {
            System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
        }
    }
    protected void handleConnection(Socket connectionToHandle) {
        PooledConnectionHandler.processRequest(connectionToHandle);
    }
    public static void main(String[] args) {
        PooledRemoteFileServer server = new PooledRemoteFileServer(3000, 3);
        server.setUpHandlers();
        server.acceptConnections();
    }
    public void setUpHandlers() {
    	//可以把这些线程放到一个数组当中,来进行统一管理
        for (int i = 0; i < maxConnections; i++) {
            PooledConnectionHandler currentHandler = new PooledConnectionHandler();
            new Thread(currentHandler, "Handler " + i).start();
        }
    }



}
 

连接池处理器:

package com.socket.poolSocketServer;

import java.io.*;
import java.net.*;
import java.util.*;

public class PooledConnectionHandler implements Runnable {
    protected Socket connection;
    //静态变量,即所有对象共享该变量
    //以该类为目标创建的线程,将共同等待这个连接池,
    //一旦该连接池中有对象,则通知等待的线程
    protected static List pool = new LinkedList();
    public PooledConnectionHandler() {
    }
    public void handleConnection() {
        try {
            PrintWriter streamWriter = new PrintWriter(connection.getOutputStream());
            BufferedReader streamReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

            String fileToRead = streamReader.readLine();
            BufferedReader fileReader = new BufferedReader(new FileReader(fileToRead));

            String line = null;
            while ((line = fileReader.readLine()) != null)
                streamWriter.println(line);

            fileReader.close();
            streamWriter.close();
            streamReader.close();
        } catch (FileNotFoundException e) {
            System.out.println("Could not find requested file on the server.");
        } catch (IOException e) {
            System.out.println("Error handling a client: " + e);
        }
    }
    //向连接池中添加连接对象,可以在此处控制任务的最大数目(类似超市中待结账的消费者)
    //而等待中的线程类似N多结账的窗口
    public static void processRequest(Socket requestToHandle) {
    	//对共享对象操作时(增加,删除,修改),要考虑到同步
    	//获取互斥锁
        synchronized (pool) {
            pool.add(pool.size(), requestToHandle);
            pool.notifyAll();
        }
    }
    public void run() {
    	//条件可以为一个boolean类型的变量,以便停止线程
        while (true) {
        	//获取互斥锁
            synchronized (pool) {
                while (pool.isEmpty()) {
                    try {
                    	//调用此方法的时候,会放弃对象锁
                        pool.wait();
                    } catch (InterruptedException e) {
                        return;
                    }
                }
                connection = (Socket) pool.remove(0);
            }
            handleConnection();
        }
    }
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值