热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在Java中为自定义聊天室创建Server类和Client类

如何解决《在Java中为自定义聊天室创建Server类和Client类》经验,为你挑选了1个好方法。

我的计划说明

我使用Java创建了一个聊天室服务器,它包含3个类,一个服务器类,一个用户类和一个聊天室类.我还创建了一个与服务器交互的客户端类.每次客户端连接到服务器时,服务器都会创建一个用户对象.每个用户对象跟踪用户所在的聊天室并运行一个侦听用户输入的线程.服务器对象循环遍历每个聊天室,以查看它是否在上周使用过.

问题

我想知道如何使用客户端对象实际连接到我的服务器.目前我打开了两个eclipse实例.我在一个中运行我的服务器程序,在另一个中运行我的客户端程序,但是我在控制台中都没有收到任何内容,这应该发生,因为服务器应该向客户端发送信息,然后客户端将在控制台上显示.然后,客户端上的人可以提供客户端将采取的输入并发送到服务器.

我想知道为什么现在什么也没发生,我可以做些什么改进.


主文件


Server.java

/*
 * Creates a server that can host up to 10 clients who can join chat rooms, post messages in chatrooms, and view posts made by other clients within the same chat room
 */
public class Server implements Runnable{
    protected ArrayList userList; //A list of users, where each user is a client connected to the server
    protected LinkedList chatRooms;   //A list of chatrooms where each client can post messages in, where messages can be seen by all clients in the chatroom
    private ServerSocket serverSocket;  //The socket for the server

    /*
     * Constructor for the server class. Initializes the server attributes,
     */
    public Server() {
        this.userList = new ArrayList(10);
        this.chatRooms = new LinkedList();
        try {
            this.serverSocket = new ServerSocket(5000);
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Creates a new user when a client connects to the server, and starts a user thread
     */
    public void createUser() {
        try {
            Socket userSocket = serverSocket.accept();
            Thread user = new Thread(new User(userSocket, this));
            user.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Creates a chatroom for clients to interact in
     * @param roomName: The name of the chat room to be created
     */
    protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        return room;
    }

    /*
     * Receives messages from clients and performs actions based on the requests of the client
     * (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    public void run() {
        long currentTime;
        while(true) {
            try {
                currentTime = System.currentTimeMillis() / 1000;
                //Loop through each chatroom and check if the chatroom has been used(joined or had a message sent to it) and remove that chatroom if it hasn't been used in a week
                for (int i = 0; i = chatRooms.get(i).dateLastUsed) {
                        chatRooms.remove(i);
                        //Also remove the chatroom from clients lists of chatrooms
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }   

    public static void main(String args[]) {
        Server server = new Server ();
        server.run();
    }
}

Client.java

public class Client extends Thread{
    private String ip = "127.0.0.1";
    private int port = 5000 ;
    private Socket socket;
    private DataInputStream iStream;
    private DataOutputStream oStream;
    private String input;

    public Client() {
        try {
            this.socket = new Socket(ip, port);
            this.iStream = new DataInputStream(socket.getInputStream());
            this.oStream = new DataOutputStream(socket.getOutputStream());
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * Sends a message to the user
     * @param message: The message to be sent to the user
     */
    protected void send (String message) {
        try {
            oStream.writeUTF(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Closes the connection to the client
     */
    protected void close () {
        try {
            iStream.close();
            oStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Runs a thread for the client to constantly receive the clients input(non-Javadoc)
     * @see java.lang.Thread#run()
     */
    public void run() {
        try {
            Scanner reader = new Scanner(System.in);
            input = iStream.readUTF();
            String userInput;//Check if there is input from the user
            while (input != null) {
                input = iStream.readUTF();
                System.out.println(input);
                userInput = reader.next();
                oStream.writeUTF(userInput);
            }
            reader.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        Client client = new Client();
        client.run();
    }

}

Server.java使用的对象


User.java

//Each user represents a client that has connected to the server
public class User implements Runnable{
    private DataInputStream inputStream;
    private DataOutputStream outputStream;
    private Socket socket;
    private String name;
    protected LinkedList chatRooms;
    private String input;
    private Server server;

    /*
     * User Constructor, create a user for each client connecting to the server
     * @socket The socket that the user will be communicated through
     * The client is prompted to create a name for themself, they are they prompted to do an action.
     */
    public User(Socket socket, Server server) {
        this.socket = socket;
        this.server = server;
        try {
            inputStream = new DataInputStream(socket.getInputStream());
            outputStream = new DataOutputStream(socket.getOutputStream());
            outputStream.writeUTF("Enter a name");
            this.name = inputStream.readUTF();
            String message = "Create a chatroom: create \nList Chat Rooms: list \n Join Chat Room: join \n Leave Chat Room: Leave";
            send(message);
        } catch (IOException e) {   
        }
    }

    /*
     * Returns the current amount of chatrooms this user is in
     */
    protected int chatRoomLength () {
        return this.chatRooms.size();
    }

    /*
     * Gets the most recent input from the user
     */
    protected String getInput() {
        return input;
    }

    /*
     * Puts a user/client in a chatroom
     * @param cRoom: The chatroom that the user will join 
     */
    protected void joinRoom (Chatroom cRoom) {
        chatRooms.add(cRoom);
    }

    /*
     * Removes a user/client from a chatroom
     */
    protected void leaveRoom (Chatroom c) {
        chatRooms.removeFirstOccurrence(c);
    }

    /*
     * Sends a message to the user
     * @param message: The message to be sent to the user
     */
    protected void send (String message) {
        try {
            outputStream.writeUTF(message);
        } catch (IOException e) {
        }
    }

    /*
     * Closes the connection to the client
     */
    protected void close () {
        try {
            inputStream.close();
            outputStream.close();
            socket.close();
        } catch (IOException e) {}
    }

    /*
     * Runs a thread for the client to constantly receive the clients input(non-Javadoc)
     * @see java.lang.Thread#run()
     */
    public void run() {
        try {
            input = inputStream.readUTF();  //Check if there is input from the user
            //if the user has disconnected from the server, remove them from the list
            if (input == null) {
                this.close();
                this.server.userList.remove(this);
            }else if (input.equals("create")){  //create a chat room
                this.send("Name the Chatroom");
                input = this.getInput();
                Chatroom c = this.server.createChatRoom(input);
                this.joinRoom(c);
            }else if (input.equals("list")) {   //List the current chatrooms
                String rooms = "";
                for (int j = 0; j


Chatroom.java

public class Chatroom {
    private String name;        //Name of the chatroom
    protected LinkedList messages;  //List of text messages that have been sent by users to the chatroom and are displayed in the chatroom
    protected long dateLastUsed;        //The last time the chatroom was joined or had a message sent to it
    protected LinkedList users;   //The clients/users that are currently in the chatroom

    /*
     * Chatroom constructor
     * @param name The name of the chatroom, as determined by the user creating it
     */
    public Chatroom(String name) {
        dateLastUsed = System.currentTimeMillis() / 1000;       //Sent the time that the chatroom was used last to the current UNIX Epoch time
        messages = new LinkedList();
        this.name = name;
    }

    /* 
     * Adds a message into the chatroom
     * @param message The message to be added to the chatroom
     */
    protected void addMessage(String message) {
        messages.add(message);
        dateLastUsed = System.currentTimeMillis() / 1000;
    }

    /*
     * Returns the name of the chatroom
     * @return String equal to the name of the chatroom
     */
    protected String getName() {
        return this.name;
    }

}

小智.. 6

首先,没有调用createUser()哪个代码接受套接字连接.

接下来是这个代码的run()功能,

try {
            Scanner reader = new Scanner(System.in);
            input = iStream.readUTF();
            String userInput;//Check if there is input from the user
            while (input != null) {
                input = iStream.readUTF();
                System.out.println(input);
                userInput = reader.next();
                oStream.writeUTF(userInput);
}

一旦套接字被接受,服务器就打印Enter a name出存储的输入,在while循环内有另一个readUTF()调用.

readUTF()调用的问题在于它是阻塞的,即.如果没有writeUTF()来自服务器的呼叫则等待数据.

我通过以下片段解决了这个问题,

try {
            Scanner reader = new Scanner(System.in);
            String userInput;//Check if there is input from the user
            do {
                input = iStream.readUTF();
                System.out.println(input);
                userInput = reader.next();
                oStream.writeUTF(userInput);
            } while (input != null);
            reader.close();
        }

即使这不是最佳解决方案,因为每次都需要Server将某些内容写入流中.

另一个解决方案是使用不同的线程进行读写,这样我们就可以创建像聊天一样的全双工,这与半双工不同.

由于没有初始化chatRoomsLinkedList,所以有一些NPE ,

加上一些逻辑错误,例如,不将chatRooms添加到其List中.

错误的代码:

protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        return room;
    }

更正代码:

protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        this.chatRooms.add(room);
        return room;
    } 

解决所有错误的最佳方法是Github和一些贡献者:p



1> 小智..:

首先,没有调用createUser()哪个代码接受套接字连接.

接下来是这个代码的run()功能,

try {
            Scanner reader = new Scanner(System.in);
            input = iStream.readUTF();
            String userInput;//Check if there is input from the user
            while (input != null) {
                input = iStream.readUTF();
                System.out.println(input);
                userInput = reader.next();
                oStream.writeUTF(userInput);
}

一旦套接字被接受,服务器就打印Enter a name出存储的输入,在while循环内有另一个readUTF()调用.

readUTF()调用的问题在于它是阻塞的,即.如果没有writeUTF()来自服务器的呼叫则等待数据.

我通过以下片段解决了这个问题,

try {
            Scanner reader = new Scanner(System.in);
            String userInput;//Check if there is input from the user
            do {
                input = iStream.readUTF();
                System.out.println(input);
                userInput = reader.next();
                oStream.writeUTF(userInput);
            } while (input != null);
            reader.close();
        }

即使这不是最佳解决方案,因为每次都需要Server将某些内容写入流中.

另一个解决方案是使用不同的线程进行读写,这样我们就可以创建像聊天一样的全双工,这与半双工不同.

由于没有初始化chatRoomsLinkedList,所以有一些NPE ,

加上一些逻辑错误,例如,不将chatRooms添加到其List中.

错误的代码:

protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        return room;
    }

更正代码:

protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        this.chatRooms.add(room);
        return room;
    } 

解决所有错误的最佳方法是Github和一些贡献者:p


推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
author-avatar
fion依依315
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有