java server 多client异步socket通信demo

来源:互联网 发布:云计算的安全问题 编辑:程序博客网 时间:2024/06/05 07:13

本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 = "";                while (!(msg = mMsgQueue.pop()).equals(MSG_QUIT)) {                    onMsgSendStart(msg);                    out.println(msg);                    onMsgSendEnd(msg, true);                }                out.close();            } catch (IOException e) {                e.printStackTrace();            }            System.out.println("Sender ... end --- " + Thread.currentThread().getName());        }    }    private class Receiver implements Runnable {        @Override        public void run() {            System.out.println("Receiver ... start --- " + Thread.currentThread().getName());            try {                BufferedReader in = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));                String msg = "";                while ((msg = in.readLine()) != null){                    onMsgReceived(msg);                }                in.close();                pushMsg(MSG_QUIT);//quit sender                onSocketClosedRemote();            } catch (IOException e) {                //e.printStackTrace();                onSocketClosedSelf();            }            System.out.println("Receiver ... end --- " + Thread.currentThread().getName());        }    }    public final void pushMsg(String msg) {        mMsgQueue.push(msg);    }    public final void quit() {        pushMsg(MSG_QUIT);//quit sender        try {            if (mSocket != null) {                mSocket.close();                mSocket = null;            }        } catch (IOException e) {            e.printStackTrace();        }    }    public final Socket getSocket() {        return mSocket;    }    private void onSocketClosedSelf() { }    protected void onSocketClosedRemote() { }    protected void onMsgSendStart(String msg) { }    protected void onMsgSendEnd(String msg, boolean success) { }    protected void onMsgReceived(String msg) { }    protected void onMsgInput(String msg) { }}
MyServer.java

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Iterator;import java.util.Map;public class MyServer {    private static final int PORT = 9876;    private static final int MAX_CLIENT_COUNT = Integer.MAX_VALUE;    private ServerSocket mSS;    private Map<String, Client> mClients = new HashMap<String, Client>();    public MyServer() {        try {            mSS = new ServerSocket(PORT);        } catch (IOException e) {            e.printStackTrace();        }    }    public void startServer() {        new Thread(new PushThread(), "PushThread").start();        try {            while (mClients.size() < MAX_CLIENT_COUNT) {                Socket socket = mSS.accept();                new Thread(new LoginThread(socket), "LoginThread").start();            }        } catch (IOException e) {            e.printStackTrace();        }    }    private class LoginThread implements Runnable {        private static final int MAX_TRY = 3;        private Socket mSocket;        public LoginThread(Socket socket) {            mSocket = socket;        }        @Override        public void run() {            System.out.println("LoginThread ... start --- " + Thread.currentThread().getName());            String id = waitForLogin();            if (id != null) {                Client client = new Client(mSocket, id);                mClients.put(id, client);                System.out.println("A new socket(" + mSocket + ") connected." +                        " Client size: " + mClients.size());//                tellAllClientChanged();            } else {                try {                    mSocket.close();                    mSocket = null;                } catch (IOException e) {                    e.printStackTrace();                }            }            System.out.println("LoginThread ... end --- " + Thread.currentThread().getName());        }                private String waitForLogin() {            String loginId = null;            try {                BufferedReader in = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));                PrintWriter out = new PrintWriter(mSocket.getOutputStream(),true);                for (int i = MAX_TRY; i > 0; i--) {                    out.println("Login: you can try " + i + " times.");                    out.println("Please input your id:");                    String id = in.readLine();                    if (!isUserExist(id)) {                        out.println("User (" + id + ") not exist!");                        continue;                    }                    out.println("Please input your password:");                    String pwd = in.readLine();                    if (!isPwdCorrect(id, pwd)) {                        out.println("Password error!");                        continue;                    }                    if (isRepeatLogin(id)) {                        out.println("User (" + id + ") is already online!");                        continue;                    } else {                        loginId = id;                        break;                    }                }                //in.close();//do not close here                if (loginId == null) {                    out.println("I'm so sorry! Login failed!");                } else {                    out.println("Welcome " + loginId + "! Login success!");                }            } catch (IOException e) {                //e.printStackTrace();            }            return loginId;        }                private boolean isUserExist(String id) {            return true;//TODO        }                private boolean isPwdCorrect(String id, String pwd) {            return (id.equals(pwd));//TODO        }                private boolean isRepeatLogin(String id) {            return mClients.containsKey(id);        }    }//    private void tellAllClientChanged() {//        Iterator<String> iterator = mClients.keySet().iterator();//        while (iterator.hasNext()) {//            String id = iterator.next();//            Client client = mClients.get(id);//            Socket socket = client.getSocket();//            String ip = socket.getInetAddress().toString();//            int port = socket.getPort();//            pushMsgToAllClient("-------------["+id+"]" + ip + ":" + port);//        }//    }    class Client extends SocketUtil {        private String mId;        public Client(Socket socket, String id) {            super(socket);            mId = id;        }        @Override        protected void onMsgSendStart(String msg) {            System.out.println("to <" + mId + ">: " + msg);        }        @Override        protected void onMsgReceived(String msg) {            System.out.println("[" + mId + "]: " + msg);            pushMsg("Your msg is: " + msg);        }        protected void onSocketClosedRemote() {            mClients.remove(mId);            System.out.println("Client (" + mId + ") offline. Client size: " + mClients.size());//            tellAllClientChanged();        }    }    private class PushThread implements Runnable {        @Override        public void run() {            System.out.println("PushThread ... start --- " + Thread.currentThread().getName());            try {                BufferedReader sysIn = new BufferedReader(new InputStreamReader(System.in));                String msg = "";                while (!(msg = sysIn.readLine()).equals(SocketUtil.MSG_QUIT)) {                    pushMsgToAllClient(msg);                }                sysIn.close();                closeServer();            } catch (IOException e) {                e.printStackTrace();            }            System.out.println("PushThread ... end --- " + Thread.currentThread().getName());        }    }    private void pushMsgToAllClient(String msg) {        Iterator<String> iterator = mClients.keySet().iterator();        while (iterator.hasNext()) {            String id = iterator.next();            Client client = mClients.get(id);            System.out.println("push message to [" + id + "]" + client);            client.pushMsg(msg);        }    }    private void closeServer() {        Iterator<String> iterator = mClients.keySet().iterator();        while (iterator.hasNext()) {            String id = iterator.next();            Client client = mClients.get(id);            System.out.println("Close [" + id + "]" + client);            client.quit();        }        try {            mSS.close();        } catch (IOException e) {            e.printStackTrace();        }    }}
MyClient.java

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;public class MyClient {    private static final String SEVER_IP = "127.0.0.1";    private static final int SEVER_PORT = 9876;    private Socket mSocket;    private ClientSocketUtil mSocketUtil;    public MyClient() {        try {            mSocket = new Socket(SEVER_IP, SEVER_PORT);            System.out.println("My socket: " + mSocket);        } catch (IOException e) {            e.printStackTrace();        }    }    public void connect() {        new Thread(new PushThread(), "PushThread").start();        mSocketUtil = new ClientSocketUtil(mSocket);    }    private class ClientSocketUtil extends SocketUtil {//TODO socket from who to who        public ClientSocketUtil(Socket socket) {            super(socket);        }        @Override        protected void onMsgSendStart(String msg) {            System.out.println("[ME]: " + msg);        }        @Override        protected void onMsgReceived(String msg) {            System.out.println("[SERVER]: " + msg);        }        @Override        protected void onSocketClosedRemote() {            socketClosedRemote = true;            System.out.println("Remote socket closed, input any words to quit.");        }    }    private boolean socketClosedRemote = false;    private class PushThread implements Runnable {        @Override        public void run() {            System.out.println("PushThread ... start --- " + Thread.currentThread().getName());            try {                BufferedReader sysIn = new BufferedReader(new InputStreamReader(System.in));                String msg = "";                while (!socketClosedRemote && !(msg = sysIn.readLine()).equals(SocketUtil.MSG_QUIT)) {                    mSocketUtil.pushMsg(msg);                }                sysIn.close();                mSocketUtil.quit();            } catch (IOException e) {                e.printStackTrace();            }            System.out.println("PushThread ... end --- " + Thread.currentThread().getName());        }    }}

完整code打包下载:http://download.csdn.net/detail/kingodcool/8747149
0 0