两个客户端通信的socket简单实现

来源:互联网 发布:百度云资源淘宝暗语 编辑:程序博客网 时间:2024/06/11 02:02

两个客户端通信的socket简单实现

这段时间学习了socket,根据简单的服务器与客户端通信,做了一个两个客户端通过服务器来进行通信的小程序。


首先定义一个简单的消息类Message,该类只有两个属性,一个是接收消息的客户端的编号,一个是消息内容,代码如下::

import java.io.Serializable;public class Message implements Serializable {    // 客户端编号    int id;    // 消息内容    String msg;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }}

接下来先创建服务器端,SocketNotifyServer类,该类创建了serverSocket对象,绑定本地的8888端口,声明静态变量sessionMap来保存所有已连接的客户端,并给每个客户端分配一个编号:

import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;public class SocketNotifyServer {    // socket服务    ServerSocket serverSocket = null;    // 用来存放已连接的客户端的socket会话    static Map<Integer, Socket> sessionMap = new HashMap<Integer, Socket>();    public void socket() {        try {            // 创建serverSocket,绑定端口为8888            serverSocket = new ServerSocket(8888);            System.out.println("服务器开启。。。");            // 客户端编号            int i = 1;            // 实现多个客户端连接            while (true) {                Socket socket = serverSocket.accept();                System.out.println("客户端" + i + "连接成功。。。");                if (socket != null) {                    // 将socket放入map,key为客户端编号                    sessionMap.put(i, socket);                    // 开启线程处理本次会话                    Thread thread = new Thread(new NotifyHandler(socket, sessionMap));                    thread.setDaemon(true);                    thread.start();                    i++;                }            }        } catch (IOException e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws IOException {        new SocketNotifyServer().socket();    }}

接下来是消息处理类,通过重写的构造方法,得到消息发送方以及所有的已连接客户端。
通过ObjectInputStream和ObjectOutputStream来对message对象进行读写:

import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Map;public class NotifyHandler extends Thread {    Socket socket = null;    InputStream in = null;    Map<Integer, Socket> sessionMap = null;    public NotifyHandler(Socket socket, Map<Integer, Socket> sessionMap) {        this.socket = socket;        this.sessionMap = sessionMap;    }    public void run() {        try {            in = socket.getInputStream();            ObjectInputStream ois = new ObjectInputStream(in);            // 实现一次连接多次通话            while (true) {                try {                    Message msg = (Message) ois.readObject();                    System.out.println("消息接受对象:客户端" + msg.getId() + ",消息内容:" + msg.getMsg());                    // 发送数据                    try {                        Socket targetSocket = sessionMap.get(msg.getId());                        OutputStream out = targetSocket.getOutputStream();                        ObjectOutputStream oos = new ObjectOutputStream(out);                        oos.writeObject(msg);                        System.out.println("服务端已转发");                    } catch (IOException e) {                        e.printStackTrace();                    }                    if (socket.isClosed()) {                        break;                    }                } catch (IOException e) {                    e.printStackTrace();                    try {                        socket.close();                        break;                    } catch (IOException e1) {                        e1.printStackTrace();                    }                } catch (ClassNotFoundException e) {                    e.printStackTrace();                }            }        } catch (IOException e) {            e.printStackTrace();        }    }}

最后是客户端的代码,由于没有界面以及其他原因,在客户端这里直接是默认[客户端1][客户端2]进行通信,所以代码中message对象的id属性是写死的,当[客户端1]启动的时候id属性的值为2,当[客户端2]启动时,id属性为1。此处把消息接收代码放在前面,是因为while (true){input = new InputStreamReader(System.in);这里在阻塞着等待输入,如果接收消息的代码放在这段代码下方,会导致在没有发过消息的时候,接收消息的线程不会启动,收不到别的客户端发来的消息:

import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.net.Socket;public class MsgSocketClient {    Socket socket = null;    InputStreamReader input = null;    InputStream in = null;    OutputStream out = null;    /**      * @param args      */    public void socketStart() {        try {            socket = new Socket("127.0.0.1", 8888);            System.out.println("客户端1启动.......");            // 接受返回数据            new Thread() {                public void run() {                    try {                        while (true) {                            in = socket.getInputStream();                            ObjectInputStream ois = new ObjectInputStream(in);                            Message msg = (Message) ois.readObject();                            System.out.println("返回数据:" + msg.getMsg());                        }                    } catch (Exception e) {                        e.printStackTrace();                    }                }            }.start();            out = socket.getOutputStream();            ObjectOutputStream oos = new ObjectOutputStream(out);            while (true) {                input = new InputStreamReader(System.in);                String msg = new BufferedReader(input).readLine();                Message message = new Message();                message.setId(2);                message.setMsg(msg);                oos.writeObject(message);                System.out.println("已发送");            }        } catch (Exception e) {            e.printStackTrace();        } finally {            // 关闭流和连接            try {                in.close();                out.close();                socket.close();            } catch (Exception e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) {        new MsgSocketClient().socketStart();    }}

运行结果如下图:
这里写图片描述
这里写图片描述
这里写图片描述


注意: in = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(in);
这里不能直接写成 ObjectInputStream ois = (ObjectInputStream)socket.getInputStream();
直接强转会报异常。

阅读全文
0 0