ServerSocket 用法

ServerSocket 选项

SO_TIMEOUT:表示等待客户连接的超时时间。

SO_REUSEADDR:表示是否允许重用服务器所绑定的地址。

SO_RCVBUF:表示接收数据的缓冲区的大小。



我们先实现一个简单的服务器

package multithread1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class EchoServer {

	private int port = 8000;
	private ServerSocket serverSocket;

	public EchoServer() throws IOException {

		serverSocket = new ServerSocket(port);
		System.out.println("服务器启动");

	}

	public void service() {
		while (true) {
			Socket socket = null;
			try {
				socket = serverSocket.accept();
				Thread workThread = new Thread(new Handler(socket));
				workThread.start();

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();

			}
		}
	}
	
	
	public static void main(String args[]) throws IOException {
		new EchoServer().service();
	}

	class Handler implements Runnable {
		private Socket socket;

		public Handler(Socket socket) {
			this.socket = socket;

		}

		private PrintWriter getWriter(Socket socket) throws IOException {
			OutputStream socketOut = socket.getOutputStream();
			return new PrintWriter(socketOut, true);

		}

		private BufferedReader getReader(Socket socket) throws IOException {
			InputStream socketIn = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));

		}

		public String echo(String msg) {
			return "echo:" + msg;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				System.out.println("New connection accepted "
						+ socket.getInetAddress() + ":" + socket.getPort());
				BufferedReader br = getReader(socket);
				PrintWriter pw = getWriter(socket);
				String msg = null;
				while ((msg = br.readLine()) != null) {
					System.out.println(msg);
					pw.println(echo(msg));
					if (msg.equals("bye")) 
						break;
				}

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
				
			}finally
			{
				try {
					if (socket != null) 
						socket.close();
					
				} catch (IOException e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}

		}

	}
}


多线程的例子

ThreadPoolTester

package multithread1;

public class ThreadPoolTester {

	public static void main(String[] args) {
		
		int num1 = 5;
		int num2 = 3;

		
		
		int numTasks = num1; //Integer.parseInt(args[0]);
		int poolSize = num2; //Integer.parseInt(args[1]);
		
		ThreadPool threadPool = new ThreadPool(poolSize);
		for (int i = 0; i < numTasks; i++) {
			threadPool.execute(createTask(i));
			
		}
		threadPool.join();
		
		
		
	}
	
	private static Runnable createTask(final int taskID) {
		return new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("TASK " + taskID + ":start");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO: handle exception
					System.out.println("Task " + taskID + ":end");
				}
				
			}
		};
	}
	
}



多线程服务器例子

线程池代码:

ThreadPool

package multithread1;

import java.util.LinkedList;

public class ThreadPool extends ThreadGroup{

	private boolean isClosed = false;  //线程池是否关闭
	private LinkedList<Runnable> workQueue; //表示工作队列
	private static int threadPoolID;        //表示线程池ID
	
	private int threadID;					//表示工作线程ID
	
	
	
	//poolSize 指定线程池中得工作线程数目
	public ThreadPool(int poolSize) {
		super("ThreadPool-" + (threadPoolID++));
		// TODO Auto-generated constructor stub
		setDaemon(true);
		//创建工作队列
		workQueue = new LinkedList<Runnable>();
		for (int i = 0; i < poolSize; i++) {
			new WorkThread().start();   //创建并启动工作线程
			
		}
	}
	
	//向工作队列中加入一个新任务,由工作线程去执行该任务
	public synchronized void execute(Runnable task) {
		if (isClosed) {
			//线程池被关闭则抛出IllegalStateException异常
			throw  new IllegalStateException();
			
		}
		if (task != null) {
			workQueue.add(task);
			//唤醒正在getTask()方法中等待任务的工作线程
			notify();
		}
	}
	
	//从工作队列中取出一个任务,工作线程会调用此方法
	protected synchronized Runnable getTask()throws InterruptedException {
		
		while (workQueue.size() == 0) {
			if (isClosed) {
				return null;
			}
			//如果工作队列中没有任务,就等待任务
			wait();
		}
		return workQueue.removeFirst();
		
	}
	//关闭线程池
	public synchronized void close() {
		if (isClosed) {
			isClosed = true;
			//清空工作队列
			workQueue.clear();
			interrupt();
		}
	}
	
	//等待工作线程把所有任务执行完
	public void join() {
		synchronized (this) {
			isClosed = true;
			
			notifyAll();//唤醒还在getTask()方法中等待任务额工作流程
		}
		
		Thread[] threads = new Thread[activeCount()];
		//enumerate()方法继承自ThreadGroup类,获得线程组中当期所有活着的工作流程
		int count = enumerate(threads);
		//等待所有工作线程运行结束
		for (int i = 0; i < count; i++) {
			try {
				threads[i].join();//等待工作线程运行结束
			} catch (InterruptedException e) {
				// TODO: handle exception
			}
		}
		
	}
	
	
	//内部类:工作线程
	private class WorkThread extends Thread
	{
		public WorkThread () {
			//加入到当前ThreadPool 线程组中
			super(ThreadPool.this,"WorkThread-" + (threadID++));
			
		}
		
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			while (!isInterrupted()) {
				Runnable task = null;
				try {
					//取出任务
					task = getTask();
					
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
				//如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程
				if (task == null) {
					return;
				}
				
				try {//运行任务,异常在catch 代码块中捕获
					task.run();
					
				} catch (Throwable e) {
					// TODO: handle exception
					e.printStackTrace();
					
				}
			}
			
		}
	}
	

	
}


多线程服务器:

EchoServer

package multithread1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class EchoServer {

	private int port = 8000;
	private ServerSocket serverSocket;
	private ThreadPool threadPool;
	private final int POOL_SIZE = 4;
	
	

	public EchoServer() throws IOException {

		serverSocket = new ServerSocket(port);
		/*
		 * 创建线程池
		 * Runtime 的availableProcessors()方法返回当前系统的CPU的数目
		 * 系统的CPU越多,线程池中的工作线程的数目也越多
		 * */
		threadPool = new ThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
		
		System.out.println("服务器启动");

	}

	public void service() {
		while (true) {
			Socket socket = null;
			try {
				socket = serverSocket.accept();
				threadPool.execute(new Handler(socket));
				

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();

			}
		}
	}
	
	
	public static void main(String args[]) throws IOException {
		new EchoServer().service();
	}

	class Handler implements Runnable {
		private Socket socket;

		public Handler(Socket socket) {
			this.socket = socket;

		}

		private PrintWriter getWriter(Socket socket) throws IOException {
			OutputStream socketOut = socket.getOutputStream();
			return new PrintWriter(socketOut, true);

		}

		private BufferedReader getReader(Socket socket) throws IOException {
			InputStream socketIn = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));

		}

		public String echo(String msg) {
			return "echo:" + msg;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				System.out.println("New connection accepted "
						+ socket.getInetAddress() + ":" + socket.getPort());
				BufferedReader br = getReader(socket);
				PrintWriter pw = getWriter(socket);
				String msg = null;
				while ((msg = br.readLine()) != null) {
					System.out.println(msg);
					pw.println(echo(msg));
					if (msg.equals("bye")) 
						break;
				}

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
				
			}finally
			{
				try {
					if (socket != null) 
						socket.close();
					
				} catch (IOException e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}

		}

	}
}


使用JDK的线程池

java.util.concurrent

package multithread1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class EchoServer {

	private int port = 8000;
	private ServerSocket serverSocket;
	private ExecutorService executorService;
	
	private final int POOL_SIZE = 4;
	
	

	public EchoServer() throws IOException {

		serverSocket = new ServerSocket(port);
		/*
		 * 创建线程池
		 * Runtime 的availableProcessors()方法返回当前系统的CPU的数目
		 * 系统的CPU越多,线程池中的工作线程的数目也越多
		 * */
		
		executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
		
		
		System.out.println("服务器启动");

	}

	public void service() {
		while (true) {
			Socket socket = null;
			try {
				socket = serverSocket.accept();
				executorService.execute(new Handler(socket));
			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();

			}
		}
	}
	
	
	public static void main(String args[]) throws IOException {
		new EchoServer().service();
	}

	class Handler implements Runnable {
		private Socket socket;

		public Handler(Socket socket) {
			this.socket = socket;

		}

		private PrintWriter getWriter(Socket socket) throws IOException {
			OutputStream socketOut = socket.getOutputStream();
			return new PrintWriter(socketOut, true);

		}

		private BufferedReader getReader(Socket socket) throws IOException {
			InputStream socketIn = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));

		}

		public String echo(String msg) {
			return "echo:" + msg;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				System.out.println("New connection accepted "
						+ socket.getInetAddress() + ":" + socket.getPort());
				BufferedReader br = getReader(socket);
				PrintWriter pw = getWriter(socket);
				String msg = null;
				while ((msg = br.readLine()) != null) {
					System.out.println(msg);
					pw.println(echo(msg));
					if (msg.equals("bye")) 
						break;
				}

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
				
			}finally
			{
				try {
					if (socket != null) 
						socket.close();
					
				} catch (IOException e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}

		}

	}
}



防止死锁的代码。

package multithread1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

public class EchoServer {

	private int port = 8000;
	private ServerSocket serverSocket;
	private ExecutorService executorService;

	private final int POOL_SIZE = 4;

	private int portForShutdown = 8001;
	private ServerSocket serverSocketForShutdown;
	private boolean isShutdown = false;

	private Thread shutdownThread = new Thread() {
		public synchronized void start() {
			this.setDaemon(true);
			super.start();
		};

		public void run() {
			while (!isShutdown) {
				Socket socketForShutdown = null;
				try {
					socketForShutdown = serverSocketForShutdown.accept();
					BufferedReader br = new BufferedReader(
							new InputStreamReader(
									socketForShutdown.getInputStream()));
					String command = br.readLine();
					if (command.equals("shutdown")) {
						long beginTime = System.currentTimeMillis();
						socketForShutdown.getOutputStream().write(
								"服务器正在关闭\r\n".getBytes());
						isShutdown = true;
						// 请求关闭线程池
						// 线程池不再接收新的任务,但是会继续执行完工作队列中现有的任务
						executorService.shutdown();

						// 等待关闭线程池,每次等待的超时时间为30秒
						while (!executorService.isTerminated()) {
							executorService.awaitTermination(30,
									TimeUnit.SECONDS);

						}

						serverSocket.close();

						long endTime = System.currentTimeMillis();
						socketForShutdown
								.getOutputStream()
								.write(("服务器已经关闭" + "用" + (endTime - beginTime) + "毫秒")
										.getBytes());
						socketForShutdown.close();
						serverSocketForShutdown.close();

					} else {
						socketForShutdown.getOutputStream().write(
								"错误的命令\r\n".getBytes());
						socketForShutdown.close();
					}

				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		};

	};

	public EchoServer() throws IOException {

		serverSocket = new ServerSocket(port);
		serverSocket.setSoTimeout(60000);
		serverSocketForShutdown = new ServerSocket(portForShutdown);

		/*
		 * 创建线程池 Runtime 的availableProcessors()方法返回当前系统的CPU的数目
		 * 系统的CPU越多,线程池中的工作线程的数目也越多
		 */

		executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
				.availableProcessors() * POOL_SIZE);
		shutdownThread.start();
		System.out.println("服务器启动");

	}

	public void service() {
		while (!isShutdown) {
			Socket socket = null;
			try {
				socket = serverSocket.accept();
				socket.setSoTimeout(60000);
				executorService.execute(new Handler(socket));
				
			} catch (SocketTimeoutException e) {
				// TODO: so exception
				
			}catch (RejectedExecutionException e) {
				// TODO: handle exception
				try {
					if (socket != null) 
						socket.close();
				} catch (IOException e2) {}
				return;
				
			}catch (SocketException e) {
				// TODO: handle exception
				if (e.getMessage().indexOf("socket closed") != -1) return;
			}
			catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
				
			}
		}
	}

	public static void main(String args[]) throws IOException {
		new EchoServer().service();
	}

	class Handler implements Runnable {
		private Socket socket;

		public Handler(Socket socket) {
			this.socket = socket;

		}

		private PrintWriter getWriter(Socket socket) throws IOException {
			OutputStream socketOut = socket.getOutputStream();
			return new PrintWriter(socketOut, true);

		}

		private BufferedReader getReader(Socket socket) throws IOException {
			InputStream socketIn = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));

		}

		public String echo(String msg) {
			return "echo:" + msg;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				System.out.println("New connection accepted "
						+ socket.getInetAddress() + ":" + socket.getPort());
				BufferedReader br = getReader(socket);
				PrintWriter pw = getWriter(socket);
				String msg = null;
				while ((msg = br.readLine()) != null) {
					System.out.println(msg);
					pw.println(echo(msg));
					if (msg.equals("bye"))
						break;
				}

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();

			} finally {
				try {
					if (socket != null)
						socket.close();

				} catch (IOException e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}

		}

	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杜甲同学

感谢打赏,我会继续努力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值