2012-01-30 165 views
4

我正在从一个简单的教程,我发现一个TCP聊天服务器,我是一种新的Java。我最终将创建一个客户端类,但我一直在通过telnet测试它。我有几个问题。我已经设置了服务器以从客户端获取命令。例如关闭客户端连接的“EXIT”和打印“OK”的“用户名”。如下图所示:简单的Java聊天服务器

用户1:TIM

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 

用户2:BOB

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 

我有,我想解决三个问题:

  1. 你会注意到,当USER 1 t用户名“Tim”(他的用户名),它表示“OK”,就像我想要的一样,但它也向用户2打印了“Tim”。是否有办法让它不能发送我输入的命令?所以当我输入“Tim”时,它不会将“Tim”打印到USER 2?

  2. 当邮件发送给其他用户时,它显示谁说的。有没有办法在两个连接上打印名称?例如,当用户2说“你好”时,它在两个连接上看起来更像是“Bob:Hello”?

  3. 是否有一种方法可以跟踪整个聊天会话中所说的所有内容,并将任何用户请求的聊天内容打印出来?

这里是我的服务器代码:

// 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 

任何帮助表示赞赏。谢谢。

回答

2

我修改了你的代码按自己的喜好,做看看:

对于第一点:

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()); 
     } 
    } 

对于第2点:

在我看来,在这你打字到控制台来获取输入信息,在这种情况下,只要输入必须发送到另一端的内容,至少可以在该方法的第一行中添加修改,如broadcast(); ,以便您可以满足您对第2点的需求,或(其他您可以让服务器端将其发送回客户端,包含该名称的消息,它将像客户端将其消息发送到服务器,并且服务器将所有客户端发回。

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); 
    } 
} 

而对于第三点,你可以写你的谈话到文件或将其保存到数据库中,这曾经的办法是适当的给你。

既然你说你是Java新手,那么最好看看java.nio。这个包比以前的java.io包好。

最新编辑:

试试这个小样本代码,希望这可以做你问什么:

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++; 
     } 
    } 
} 

希望这可以帮助你以某种方式。

Regards

+0

感谢这些建议,他们帮助了很多。我有一个更快的问题。如何让它在光标前显示用户的名字?例如,在用户输入名称后,光标始终显示“用户名:”,然后光标开始后缀。 – user1174834 2012-01-30 04:33:51

+0

@ user1174834:如果你使用控制台,这有点困难,请检查我最近的编辑,这可以为你做些什么。 Regards – 2012-01-30 05:38:26

+0

感谢您的帮助。 – user1174834 2012-01-30 15:45:04

1

有没有办法让它不发送我输入的命令?所以当我 键入“Tim”时,它不会将“Tim”打印到USER 2?

您已将用户名存储在HandleClient中;当它的run方法得到输入时,它会检查用户是否输入了他的名字。所以如果他这么做,或者他输入了一个命令,就不要拨打广播。

当消息发送给其他用户时,它显示谁说的。 有两种方法可以在两个连接上打印名称?例如,当 用户2说“你好”时,在 连接上看起来更像是“Bob:Hello”?

我见过

大多数聊天客户端有一个多窗口保持对话和一个小的输入文字。用户在小窗口中输入他的文本,然后服务器将其广播回给他。因此,服务器可以在广播前在每条消息前添加用户名和冒号,这将与用户在自己的客户端上输入的内容分开。

有没有一种方法来跟踪所有的这是一个在整个 聊天会话说和打印出来的聊天的全部内容,以任何 用户请求呢?

当然。随时随地将它们全部写入文件。看看java.io.FileWriter。

+1

有一个简单的例子[这里](http://stackoverflow.com/a/3245805/230513)。 – trashgod 2012-01-30 03:29:51