即时通讯程序(socket 编程基础)

这几天开始学习java的网络编程,根据这个程序对socket编程进行初步了解.


程序效果图:


源代码(注释很详细):

Message类:

public class Message implements Serializable{
    private String from;//sender
    private String to;  //target
    private String info;//message
    private int type;   //type
    .........
}

MessageType类:

public final class MessageType {
    public static final int TYPE_LOGIN =0x1;
    public  static final  int TYPE_SEND =0x2;
}

Server端:

public class Server {
    public static void main(String[] args) {
        //保存客户端处理的线程
        Vector<UserThread> vector = new Vector<>();
        ExecutorService es = Executors.newFixedThreadPool(5);
        //创建服务器端的Socket
        try {
            ServerSocket server = new ServerSocket(8888);
            System.out.println("服务器已启动,等待连接:");
            while (true) {
                Socket socket = server.accept();
                UserThread user = new UserThread(socket, vector);
                es.execute(user);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/*
客户端处理线程
 */
class UserThread implements Runnable {
    private String name;//客户端的用户名称
    private Socket socket;//服务器连接的客户端的socket
    Vector<UserThread> vector;//用来传入服务器的线程池
    private ObjectInputStream ois;//输入流,接收信息
    private ObjectOutputStream oos;//输出流,发送信息
    private boolean flag = true;//控制循环的标记

    public UserThread(Socket socket, Vector<UserThread> vector) {//传入线程要使用的socket和vector
        this.socket = socket;
        this.vector = vector;
        vector.add(this);
    }

    @Override
    public void run() { //开跑
        try {
            System.out.println("客户端" + socket.getInetAddress().getHostAddress() + "已连接");//先说明连接上的客户端
            ois = new ObjectInputStream(socket.getInputStream());//装入客户端发来的信息流
            oos = new ObjectOutputStream(socket.getOutputStream());//要发出去的信息流
            while (flag) {   //连接后开始持续接收客户端发来的信息
                //读取消息对象
                Message msg = (Message) ois.readObject();//读到的类型要进行强制转换
                int type = msg.getType();
                switch (type) {
                    case MessageType.TYPE_SEND:
                        String to = msg.getTo();
                        //遍历vector中的名字,找到线程
                        UserThread ut;
                        int size = vector.size();
                        for (int i = 0; i < size; i++) {
                            ut = vector.get(i);
                            if (to.equals(ut.name) && ut != this) {
                                ut.oos.writeObject(msg);
                                break;
                            }
                        }
                        break;
                    case MessageType.TYPE_LOGIN:  //客户端一开始连接时发来的信息会是login类型,为了提高效率,这个情况放后面
                        name = msg.getFrom();     //获取客户端姓名(唯一)
                        msg.setInfo("欢迎你");    //同样使用msg,把info设置为欢迎你
                        oos.writeObject(msg);     //接收到login信息后发送欢迎你信息给客户端
                        break;
                    default:
                        break;
                }
            }
            ois.close();
            oos.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
client端:

public class Client {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        ExecutorService es = Executors.newSingleThreadExecutor();//单线程池
        try {
            Socket socket = new Socket("localhost", 8888);
            System.out.println("服务器连接成功");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            //先向服务器发送消息,然后在接收服务器的信息,才会收到"欢迎你"
            System.out.println("请输入你的名称");
            String name = input.nextLine();
            Message msg = new Message(name, null, null, MessageType.TYPE_LOGIN);
            objectOutputStream.writeObject(msg);
            msg = ((Message) objectInputStream.readObject());
            System.out.println(msg.getInfo() + msg.getFrom());
            //启动读取消息的线程
            ReadInfoThread read = new ReadInfoThread(objectInputStream);
            es.execute(read);
            //使用主线程实现发送消息
            boolean flag = true;
            while (flag) {  //一直可以发消息,且这时候的type都是TYPE_SEND
                msg = new Message();
                System.out.println("To:");
                msg.setTo(input.nextLine());
                msg.setType(MessageType.TYPE_SEND);
                msg.setFrom(name);
                System.out.println("info:");
                msg.setInfo(input.nextLine());
                objectOutputStream.writeObject(msg);
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

//读取消息线程
class ReadInfoThread implements Runnable {

    private ObjectInputStream in;  //服务器发来的输入流
    private boolean flag = true;   //是否读的标志

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public ReadInfoThread(ObjectInputStream in) {
        this.in = in;
    }

    @Override
    public void run() {

        try {
            while (flag) {   //一直读
                Message msg = ((Message) in.readObject());   //强制类型转换
                //除了登录的时候,服务器把info设为"欢迎你",后面的msg info都是客户端自己构造的
                System.out.println("【" + msg.getFrom() + "】对我说" + "\"" + msg.getInfo() + "\"");
            }
            if (in != null) {
                in.close();
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值