需求:通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();
}
}
}