Java之Socket简单聊天实现(QQ续二)

来源:互联网 发布:mysql gtid复制原理 编辑:程序博客网 时间:2024/05/01 13:59
今天跟大家分享一下我那QQ小项目中服务器与客户端的核心代码,并谈谈一些我的建议和看法,希望大家多多支持,你们的支持,就是我继续分享的动力,哈哈!

        一、服务器,好了,废话不多说,我们先来看看服务器部分,我这里用到线程池,至于为什么用线程池,不知道的童鞋可以去我的另一篇blog看看:http://blog.csdn.net/weidi1989/article/details/7930820。当一个用户连接上之后,我们马上将该用户的socket丢入已经建好的线程池中去处理,这样可以很快腾出时间来接受下一个用户的连接,而线程池中的这个线程又分支为两个线程,一个是读消息线程,一个是写消息线程,当然,因为我这个聊天是用来转发消息的,所以还以单例模式建了一个Map用来存放每个用户的写消息线程(如果用户多的话,这是相当消耗资源的),以便在转发消息的时候,通过Map的key就可以取出对应用户的写消息线程,从而达到转发消息的目的。具体下面再说

 

package server;import java.net.ServerSocket;import java.net.Socket;import java.util.Collection;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;import java.util.concurrent.TimeoutException;public class Server { private ExecutorService threadPool; //线程池private ServerSocket serverSocket; //服务器套接字private Socket socket; //客户端套接字private boolean isStarted; //是否循环读取消息private String ip;private int serverPort; //端口号private int size = 50;public Server() {try {int cpuNum = Runtime.getRuntime().availableProcessors();// 创建线程池,池中具有(cpu个数*50)条线程    threadPool = Executors.newFixedThreadPool(cpuNum * this.size);serverSocket = new ServerSocket(this.serverPort);} catch (Exception e) {// TODO: handle exception}}/** * 启动服务器 */public void service() {long beginTime = System.currentTimeMillis();long endTime;System.out.println("=====开始启动服务器===" + beginTime);try {while (isStarted) {//从ServerSocket中取出一个客户端连接//侦听并接受到此套接字的连接。socket = serverSocket.accept();ip = socket.getInetAddress().toString();System.out.println(" 用户:" + ip + " 已建立连接");//为支持多用户并发访问,采用线程池管理每一个用户的连接请求if (socket.isConnected()) {// 添加到线程池 threadPool.execute(new SocketTask(socket));}//循环结束后,记得关闭socket,释放资源if (socket != null) {socket.close(); }if (serverSocket != null) {serverSocket.close();}endTime = System.currentTimeMillis();System.out.println("=====服务器启动成功===耗费时间:" + (endTime - beginTime) +"毫秒 ");}} catch (Exception e) {// isStarted = false;   e.printStackTrace(); }  }/** * 服务器退出 */public void quit() {try {this.isStarted = false;  serverSocket.close(); } catch (Exception e) {e.printStackTrace();}} public void setSize(int size) {this.size = size;}/** * 功能说明 *     服务器的套接字任务 * @author Administrator * */private class SocketTask implements Runnable {private Socket socket;private InputThread in;private OutputThread out;private OutputThreadBuffer buffer; public SocketTask(Socket socket) {this.socket = socket;this.buffer = OutputThreadBuffer.getInstance();  }@Overridepublic void run() { out = new OutputThread(socket, buffer);// 先实例化写消息线程,(把对应用户的写线程存入map缓存器中)           in = new InputThread(socket, out, buffer); // 再实例化读消息线程           out.setStart(true);          in.setStart(true);          in.start();          out.start(); }}}


二、服务器写消息线程,接下来,我们来看看写消息线程,很简单的一段代码,有注释,我就不多说了:

原创粉丝点击