如何将运行在命令提示符上的客户端-服务器聊天应用程序转换为基于Web的应用程序?

6

我是一个有用的助手,可以为您翻译文本。

我使用套接字编程制作了一个多客户端服务器聊天应用程序,可以在命令提示符中部署为JAR文件。现在,我需要做出更改,以便在Web浏览器上使用Tomcat服务器运行此应用程序。

我的服务器代码:

package com.Aricent;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.*;
import java.sql.DriverManager;

public class Server {

    static ServerSocket serverSocket=null;
    static Socket clientSocket=null;
    static final int max=20;
    static clientThread[] threads=new clientThread[max];
    public static void main(String arg[])
    {
        int portNumber=2222;
        try{
        serverSocket=new ServerSocket(portNumber);
        }catch(IOException e)
        {
            System.out.println(e);
        }

        while(true)
        {
            try{
                clientSocket=serverSocket.accept();
                int i=0;
                for(i=0;i<max;i++)
                {
                    if(threads[i]==null)// searching for empty position
                    {
                        (threads[i]=new clientThread(clientSocket, threads)).start();
                        break;
                    }
                }
                if(i==max)
                {
                    PrintStream os=new PrintStream(clientSocket.getOutputStream());
                    os.println("Server too busy. Try later");
                    os.close();
                    clientSocket.close();
                }
            }catch(IOException e)
            {
                System.out.println(e);
            }
        }
    }

}


class clientThread extends Thread
{
    String clientName=null;
    DataInputStream is=null;
    PrintStream os=null;
    Socket clientSocket=null;
    clientThread[] threads;
    int max;
    String dbPath="jdbc:mysql://172.19.24.66:3306/chatdb";
    String dbUser="root";
    String dbPass="root";

    public clientThread(Socket clientSocket, clientThread[] threads)
    {
        this.clientSocket=clientSocket;
        this.threads=threads;
        max=threads.length;
    }

    public void run()
    {

        int max=this.max;
        clientThread[] threads=this.threads;
        boolean choice=false;
        String sender="";



        try{
            Class.forName("com.mysql.jdbc.Driver");
            Connection con=DriverManager.getConnection(dbPath,dbUser,dbPass);
            PreparedStatement ps=null;
            ResultSet rs=null;
            Statement stmt=con.createStatement();
            String query="";


            is=new DataInputStream(clientSocket.getInputStream());
            os=new PrintStream(clientSocket.getOutputStream());
            String name="";
            String ch="";
            boolean login=false;
            while(!login)
            {
                os.println("*** Press 1 to login or press 2 to register***");
                ch=is.readLine();
                os.println(ch);
                if(ch.equals("1"))
                {
                    os.println("Enter your username and password...");
                    String uname=is.readLine();
                    String upass=is.readLine();
                    query="Select * from user where username= '"+uname+"' and password= '"+upass+"'";
                    rs=stmt.executeQuery(query);
                    if(rs.next() && !rs.getString("status").equals("online"))
                    {
                        query="update user set status='online' where username='"+uname+"'";
                        stmt.executeUpdate(query);
                        login=true;
                        name=uname;
                    }
                    else
                        os.println("Sorry wrong credentials");
                }
                else if(ch.equals("2"))
                {
                    os.println("Enter your username and password and emailId for registration...");
                    String uname=is.readLine();
                    String upass=is.readLine();
                    String uemail=is.readLine();
                    query="Select username from user where emailId= '"+uemail+"'";
                    rs=stmt.executeQuery(query);
                    if(rs.next() )
                    {
                        os.println("Sorry user- "+rs.getString("username")+" already registered with this mail id");

                    }
                    else
                    {
                        query="insert into user (username,password,emailId,status) value('"+uname+"','"+upass+"','"+uemail+"','offline')";
                        stmt.executeUpdate(query);
                        os.println("Registration successful...");
                    }
                }
                else
                    os.println("Wrong input");
            }






            os.println("Welcome "+ name+" to chat room. \n To leave enter: /stop \n To start private chat enter: /Private USERNAME YOUR MESSAGE \n To stop private chat enter: /endPrivate");
            synchronized(this){
                for(int i=0;i<max;i++)
                {
                    if(threads[i]!=null && threads[i]==this){
                        clientName=name;
                        break;
                    }
                }

                for(int i=0;i<max;i++)
                {
                    if(threads[i]!=null&& threads[i]!=this)
                    {
                        threads[i].os.println("*NEW USER "+name+" ENTERed CHAT ROOM*");

                    }
                }
            }

            while(true)
            {
                int pos=0;
                String line=is.readLine();
                if(line.startsWith("/stop"))
                {
                    break;
                }
                if(line.startsWith("/endPrivate"))
                {
                    choice=false;

                }
                if(line.startsWith("/Private") || choice==true )
                {
                    choice=true;
                    //String words[];
                    if(line.startsWith("/Private"))
                    {
                        //pos=2;
                         String words[]=line.split("\\s",3);
                         sender=words[1];
                        synchronized(this)
                        {
                            for(int i=0;i<max;i++)
                            {
                                if(threads[i]!=null && threads[i]!=this && threads[i].clientName.equals(words[1]) )
                                {
                                    threads[i].os.println("<"+name+">"+words[2]);
                                    this.os.println(">>"+name+" "+words[2]); //showing the sender that msg is sent
                                    break;
                                }
                            }
                        }

                    }
                    else
                    {
                    String words[]=line.split("\\s",1);
                    synchronized(this)
                    {
                        for(int i=0;i<max;i++)
                        {
                            if(threads[i]!=null && threads[i]!=this && threads[i].clientName.equals(sender) )
                            {
                                threads[i].os.println("<"+name+">"+words[0]);
                                this.os.println(">>"+name+" "+words[0]); //showing the sender that msg is sent
                                break;
                            }
                        }
                    }
                    }
                    }
                else
                {
                    synchronized(this){
                        for(int i=0;i<max;i++)
                        {
                            if(threads[i]!=null  && threads[i].clientName!=null )
                            {
                                threads[i].os.println("< "+name+" > "+line);
                                //threads[i].os.println("** The user "+name+" is leaving the chat room **");
                            }
                        }

                    }
                }
            }

            //after while
            synchronized(this)
            {
                for(int i=0;i<max;i++)
                {
                    if(threads[i]!=null  && threads[i].clientName!=null )
                    {

                        threads[i].os.println("** The user "+name+" is leaving the chat room **");
                    }
                }
            }
                    os.println("** Bye "+name+" **");

                    synchronized(this)
                    {
                        for(int i=0;i<max;i++)
                        {
                            if(threads[i]==this)
                            {
                                threads[i]=null;
                            }




                }


            }
                    is.close();
                    os.close();
                    clientSocket.close();





        }catch(Exception e)
        {
            System.out.println(e);
        }




    }

}

客户端代码:

package com.Aricent;

import java.io.*;
import java.net.*;

public class Client implements Runnable {

    static Socket clientSocket=null;
    static PrintStream os=null;
    static DataInputStream is=null;
    static BufferedReader inputLine=null;
    static boolean closed=false;

    public static void main(String arg[])
    {
        int portNumber=2222;
        String host="localhost";

        try{
            clientSocket=new Socket(host,portNumber);
            inputLine=new BufferedReader(new InputStreamReader(System.in));
            os=new PrintStream(clientSocket.getOutputStream());
            is=new DataInputStream(clientSocket.getInputStream());

        }
        catch(Exception e)
        {
            System.out.println(e);
        }

        if(clientSocket!=null&&os!=null&&is!=null)
        {
            try{
                new Thread(new Client()).start();
                while(!closed)
                {
                    os.println(inputLine.readLine().trim());
                }
                os.close();
                is.close();
                clientSocket.close();
            }catch(IOException e)
            {
                System.out.println(e);
            }
        }

    }





    //@Override
    public void run() {
        // TODO Auto-generated method stub

        String responseLine;
        try{
            while((responseLine=is.readLine())!=null)
            {
                System.out.println(responseLine);
                if(responseLine.indexOf("*** Bye")!=-1)
                    break;
            }
            closed=true;
        } catch(Exception e)
        {
            System.out.println(e);
        }

    }


}

我的主要问题是如何在本地Tomcat服务器中引入套接字编程?


尝试使用AngularJS WebSockets来实现这个。我发现它对我的聊天应用程序非常好。 - mattyman
如何在客户端内创建HTML表单,其值可以替换命令行输入? - dexter
你可以在代码中使用javax.net.ssl.HttpsURLConnection来调用“ws://localhost:8080/chat-app/users”,从而使你的websocket接收和发送消息。使用“http://localhost:8080/chat-app/users”可以添加和查看用户。只是一个想法... - mattyman
你可以在任何 Java web 应用程序中启动套接字。它们的启动方式与控制台应用程序基本相同。但是,你不应该在 Servlets 中这样做,因为每个 HttpRequest 都会生成一个新的 Thread 和新的 Servlet 实例。你可以在静态初始化器或更好地在 ServletContextListener 的 contextInitialized(ServletContextEvent ctx) 方法中启动它们。 - Mitja Gustin
一般提示:请注意,在公共论坛上发布属于您雇主的代码时要小心。发布的代码似乎属于Aricent.com,可能会给您带来法律麻烦。 - Piyg
3个回答

4

几年前我发布了完整的解决方案,但它使用nodejs作为服务器。在IOS中建立使用node.js服务器的聊天应用程序。该应用程序使用服务器推送技术(Websockets)。

如果您想将当前代码迁移到浏览器中,并使其保持原样,则只需花费几周的工作时间来适应从浏览器中使用HTTP的服务器线程。浏览器通过HTTP协议与服务器通信,这是您当前解决方案上面的一层。您的解决方案使用的是纯网络套接字。

但是,您可以使用Tomcat上的servlet构建长轮询类型的应用程序和正常的Web应用程序,以重复检查服务器是否有新的聊天消息(每隔几秒钟进行一次新请求),或者尝试最新的Tomcat Websocket支持。Tomcat示例中有一个示例聊天应用程序。下载zip包,查看 /apache-tomcat-8.0.35/webapps/examples/websocket/。


以上客户端代码如何转换为Servlet?有没有办法这样做? - Deepak
如果您将应用程序迁移到浏览器,客户端是Web浏览器,服务器是Tomcat。由于浏览器将与服务器通信,因此不会有使用套接字的客户端代码。您看过Tomcat应用程序示例吗? - Mitja Gustin

2
您的应用程序完全不依赖于任何标准协议。因此,您将需要使用JavaScript从头开始重新创建客户端(以使其成为Web应用程序)。而且,使用JavaScript直接从浏览器进行套接字连接会有问题(一旦您超出本地主机连接,您将受到浏览器安全限制)。
作为一个直截了当的方法:将服务器作为jar应用程序运行,将客户端作为自定义Applet(哦!那是90年代-00年代的事情)。我猜在一两年内,Applets就会过时。
如果您使用更标准的东西(例如STOMP over WebSockets)重写应用程序,则会更好。然后,您的服务器可以部署到诸如Tomcat或Jetty之类的servlet容器中。您的客户端将是任何支持WebSockets和STOMP的内容。
根据我所看到的,您的应用程序具有身份验证和聊天室。最好将身份验证和授权交付给自定义框架(任何您喜欢的内容,只需在websocket连接中提供附加标头以合并WS连接和已建立的会话即可)。在STOMP单词中,聊天室变为目的地。因此,您需要创建一个应用程序,该应用程序会对到达STOMP目标的消息做出反应。
我建议您查看Spring框架及其对WebSockets的支持。
此外,据我所见,您正在为每个用户会话建立单独的数据库连接,这在一般情况下是浪费资源的。创建连接池,并仅在需要时使用其中一个连接。

1
你可以使用NPM来安装pusherjs。如果你使用Pusherjs,它有一个免费的计划,可以省去创建和管理套接字连接的烦恼。每个用户可以分配独立的频道(免费计划支持无限频道),消息只需要提交到该频道即可,客户端应用程序可以持续侦听该频道。非常容易上手。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接