本demo打包下载,请点击这里
本demo主要用java实现了服务器监听多客户端登录,并实现了客户端与服务器的异步socket通信,通信过程采用了消息队列缓冲机制(生产者消费者模式)。
登录过程是后来写的,用的是同步模式。密码验证采用的是和用户名相同为验证pass,可以根据需要修改。
登录3次失败后,服务器会断开该客户端的socket,客户端退出,需重新启动客户端。
登录成功后,客户端需要记住自己的id,这块忘写了。可以由服务器返回id,也可以输入id时记录(同一个地方输入,注意不要把密码当成id记录了)。
没有写客户端之间的通信,可以使用MsgPacket将发送和接收客户端id打包发给服务端,在服务端解包后,通过map和id找到接收客户端的socket,将信息发送过去。
本demo服务端可以向所有客户端发送推送消息。
本demo是在ubuntu环境下写的,用javac java命令即可编译运行。
打包资源里面有makefile,通过执行make可以编译,make runs 可以运行服务端,make runc 可以运行客户端。
没有心跳机制,可以参考 http://my.oschina.net/fengcunhan/blog/178155
下面是关键的代码。
SocketUtil.java 通信过程中的socket管理,采用了消息队列机制,并开启了Sender和Receiver两个线程处理发送和接收消息。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class SocketUtil {
public static final String MSG_QUIT = "quit";
private Socket mSocket;
private MsgQueue<String> mMsgQueue = new MsgQueue<String>();
public SocketUtil(Socket socket) {
mSocket = socket;
new Thread(new Sender(), "Sender").start();
new Thread(new Receiver(), "Receiver").start();
}
private class MsgQueue<T> {
private static final int CAPACITY = 10;
private List<T> mMsgs = new ArrayList<T>();
public synchronized void push(T msg) {
try {
while (mMsgs.size() >= CAPACITY) {
wait();
}
mMsgs.add(msg);
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized T pop() {
T msg = null;
try {
while (mMsgs.size() <= 0) {
wait();
}
msg = mMsgs.get(0);
mMsgs.remove(0);
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
return msg;
}
}
private class Sender implements Runnable {
@Override
public void run() {
System.out.println("Sender ... start --- " + Thread.currentThread().getName());
try {
PrintWriter out = new PrintWriter(mSocket.getOutputStream(),true);
String msg =