简体   繁体   English

简单的 Java 聊天服务器

[英]Simple Java Chat Server

I am making a TCP chat server from a simple tutorial I found and I'm kind of new to java.我正在根据我找到的一个简单教程制作一个 TCP 聊天服务器,而且我对 java 有点陌生。 I will eventually make a client class but I've been testing it through telnet so far.我最终会制作一个客户端类,但到目前为止我一直在通过 telnet 对其进行测试。 I have a couple of problems.我有几个问题。 I have setup the server to take commands from the client.我已经设置服务器从客户端获取命令。 For example "EXIT" which closes the client connection, and "Username" which prints "OK".例如关闭客户端连接的“EXIT”和打印“OK”的“Username”。 Shown below:如下图所示:

USER 1: TIM用户 1:蒂姆

Welcome to Bob's Chat Server!

Please Enter a User Name: 
Tim
Welcome Tim we hope you enjoy your chat today
Bob:Hello
Hi Bob
Tim
OK
EXIT
Closing Connection  . . . Goodbye

USER 2: BOB用户 2:鲍勃

Welcome to Bob's Chat Server!

Please Enter a User Name: 
Bob
Welcome Bob we hope you enjoy your chat today
Hello
Tim:Hi Bob
Tim:Tim

I have three problems that I want to address:我想解决三个问题:

  1. You'll notice that when USER 1 typed "Tim" (his username) it said "OK" like I wanted, but it also printed "Tim" to USER 2. Is there a way to make it not send my typed commands across?您会注意到,当 USER 1 输入“Tim”(他的用户名)时,它说“OK”就像我想要的那样,但它也向 USER 2 打印了“Tim”。有没有办法让它不发送我输入的命令? So when I type "Tim" it doesn't print "Tim" to USER 2?那么当我输入“Tim”时,它不会将“Tim”打印到 USER 2?

  2. When messages are sent to other users it displays who said it.当消息发送给其他用户时,它会显示是谁说的。 Is there a way to print the name on both connections?有没有办法在两个连接上打印名称? For example when USER 2 says "Hello" it looks more like "Bob: Hello" on both connections?例如,当用户 2 说“你好”时,它在两个连接上看起来更像“鲍勃:你好”?

  3. Is there a way to keep track of everything that's said in the entire chat session and print off the entire contents of the chat to whatever user requested it?有没有办法跟踪整个聊天会话中所说的所有内容并将聊天的全部内容打印到任何用户请求的地方?

Here is my server code:这是我的服务器代码:

// Chat Server runs at port no. 9020
import java.io.*;
import java.util.*;
import java.net.*;
import static java.lang.System.out;

public class  TCPServer 
{
  Vector<String> users = new Vector<String>();
  Vector<HandleClient> clients = new Vector<HandleClient>();

  int PORT = 9020;
  int NumClients = 10;

  public void process() throws Exception  
  {
      ServerSocket server = new ServerSocket(PORT,NumClients);
      out.println("Server Connected...");
      while( true) 
      {
         Socket client = server.accept();
         HandleClient c = new HandleClient(client);
         clients.add(c);
     }  // end of while
  }

  public static void main(String ... args) throws Exception 
  {
      new TCPServer().process();
  } // end of main

  public void boradcast(String user, String message)  
  {
        // send message to all connected users
        for (HandleClient c : clients)
           if (!c.getUserName().equals(user))
           {
              c.sendMessage(user,message);
           }
  }

  class HandleClient extends Thread 
  {
    String name = "";
    BufferedReader input;
    PrintWriter output;

    public HandleClient(Socket client) throws Exception 
    {
          // get input and output streams
         input = new BufferedReader(new InputStreamReader(client.getInputStream())) ;
         output = new PrintWriter (client.getOutputStream(),true);
         output.println("Welcome to Bob's Chat Server!\n");
         // read name
         output.println("Please Enter a User Name: ");
         name  = input.readLine();
         users.add(name); // add to vector
         output.println("Welcome "+name+" we hope you enjoy your chat today");
         start();
    }

    public void sendMessage(String uname,String  msg)  
    {
        output.println( uname + ":" + msg);
    }

    public String getUserName() 
    {  
        return name; 
    }

    public void run()  
    {
         String line;
         try    
         {
            while(true)   
            {
                        line = input.readLine();
                if("EXIT".equals(line))
            {
                output.println("Closing Connection  . . . Goodbye");
                            clients.remove(this);
                        users.remove(name);
                break;
                    }
            else if(name.equals(line))
            {
                            output.println("OK");
                    }
                boradcast(name,line); // method  of outer class - send messages to all
            }// end of while
         } // try
         catch(Exception e) 
         {
           System.out.println(e.getMessage());
         }
    } // end of run()
  } // end of inner class
} // end of Server

Any help is appreciated.任何帮助表示赞赏。 Thanks.谢谢。

I had modified your code as per your liking , do have a look :我已根据您的喜好修改了您的代码,请看一下:

For Point 1:对于第 1 点:

public void run()  
    {
         String line;
         try    
         {
            while(true)   
            {
                        line = input.readLine();
                if("EXIT".equals(line))
                {
                    output.println("Closing Connection  . . . Goodbye");
                    clients.remove(this);
                    users.remove(name);
                    break;
                }
                else if(name.equals(line))
                {
                    output.println("OK");
                }
                else
                {
                    // Seems to me just adding this else part will do the trick for point one.
                    boradcast(name,line); // method  of outer class - send messages to all
                }
            }// end of while
         } // try
         catch(Exception e) 
         {
           System.out.println(e.getMessage());
         }
    }

For Point 2 :对于第 2 点:

Seems to me in this you are typing to the console to get the input, in that case atleast for once you have to type what you have to send to the other side, then you can add your modification to this as shown in the first line of the method, broadcast();, so that you can satisfy your need for Point 2, or ( else You can let the server side send it back to the client, the message which containts the name, it will be like a client send his message to the server and the server is sending all the clients back. )在我看来,您正在输入控制台以获取输入,在这种情况下,至少有一次您必须输入您必须发送到另一端的内容,然后您可以添加您的修改,如第一行所示方法的broadcast();,这样就可以满足你对第2点的需要,或者( else你可以让服务端发回给客户端,包含名字的消息,就像客户端发送他向服务器发送消息,服务器正在将所有客户端发回。

public void boradcast(String user, String message)  
{
    System.out.println(user + " : " + message);
    // send message to all connected users
    for (HandleClient c : clients)
    if (!c.getUserName().equals(user))
    {
        c.sendMessage(user,message);
    }
}

And for Point 3, you can write your conversation to the file or save it to the database, which ever way is appropriate to you.对于第 3 点,您可以将对话写入文件或将其保存到数据库中,无论哪种方式都适合您。

And since you said you are new to Java, you better look atjava.nio .既然你说你是 Java 新手,你最好看看java.nio This package is better than the previous java.io package.这个包比之前的 java.io 包要好。

LATEST EDIT :最新编辑:

Try this small sample code, hope this might do what you asking for :试试这个小示例代码,希望这可以满足您的要求:

import java.io.*;

public class StringConsole
{
    public static void main(String... args) throws IOException
    {
        int count = 0;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while (count < 5)
        {
            System.out.print("My Name : ");
            String message = br.readLine();
            count++;
        }   
    }
}

Hope this might help you in some way.希望这可能对您有所帮助。

Regards问候

Is there a way to make it not send my typed commands across?有没有办法让它不发送我输入的命令? So when I type "Tim" it doesn't print "Tim" to USER 2?那么当我输入“Tim”时,它不会将“Tim”打印到 USER 2?

You already store the user name in HandleClient;您已经将用户名存储在 HandleClient 中; when its run method gets input, it checks to see if the user has typed his name.当它的 run 方法得到输入时,它会检查用户是否输入了他的名字。 So don't call broadcast if he does that, or if he enters a command.因此,如果他这样做,或者如果他输入命令,请不要调用广播。

When messages are sent to other users it displays who said it.当消息发送给其他用户时,它会显示是谁说的。 Is there a way to print the name on both connections?有没有办法在两个连接上打印名称? For example when USER 2 says "Hello" it looks more like "Bob: Hello" on both connections?例如,当用户 2 说“你好”时,它在两个连接上看起来更像“鲍勃:你好”?

Most chat clients I've seen have a multiline window to hold the conversation and a small one for entering text.我见过的大多数聊天客户端都有一个多行窗口来保存对话和一个用于输入文本的小窗口。 The user enters his text in the small window, and the server broadcasts it back to him.用户在小窗口中输入他的文本,服务器将其广播回给他。 So the server can prepend the username and colon before each message as it is broadcast, and that will be separate from what the user types in on his own client.因此,服务器可以在广播每条消息之前添加用户名和冒号,这与用户在自己的客户端上输入的内容是分开的。

Is there a way to keep track of everything that's said in the entire chat session and print off the entire contents of the chat to whatever user requested it?有没有办法跟踪整个聊天会话中所说的所有内容并将聊天的全部内容打印到任何用户请求的地方?

Sure.当然。 Write it all to a file as you go.随时将其全部写入文件。 Look at java.io.FileWriter.查看 java.io.FileWriter。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM