您的位置:首页 > 编程语言 > Java开发

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

2013-02-28 17:06 706 查看
今天跟大家分享一下我那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();
}

@Override
public void run() {

out = new OutputThread(socket, buffer);
// 先实例化写消息线程,(把对应用户的写线程存入map缓存器中)
in = new InputThread(socket, out, buffer); // 再实例化读消息线程
out.setStart(true);
in.setStart(true);
in.start();
out.start();
}

}
}


二、服务器写消息线程,接下来,我们来看看写消息线程,很简单的一段代码,有注释,我就不多说了:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: