2013-05-13 110 views
0

我正嘗試使用UDP套接字在Java中創建一個非常簡單的聊天應用程序。有一臺服務器和多個客戶端。java中的UDP套接字聊天應用程序

現在我的代碼是:

服務器:

package chat; 

import java.io.*; 
import java.net.*; 
import java.util.HashMap; 
import java.util.Set; 

class User{ 
    InetAddress addr; 
    int port; 

    User(InetAddress a,int p){ 
     addr = a; 
     port = p; 
    } 
} 



public class Server { 
    private static final int PORT = 27012; 
    private static DatagramSocket sckt; 
    private static DatagramPacket in,out; 
    private static byte[] buffer; 
    private static HashMap<String,User> users; 
    public static void main(String[] args) { 
     try{ 
      System.out.println("Opening port..."); 
      sckt = new DatagramSocket(PORT); 
      users = new HashMap<String,User>(); 

     } 
     catch(SocketException e){ 
      System.out.println("Port connection failed!"); 
      System.exit(1); 
     } 

     handleClient(); 
    } 
     private static void sendMsg(InetAddress addr, int port, String msg){ 
      try{ 
      out = new DatagramPacket(msg.getBytes(),msg.length(),addr,port); 
      sckt.send(out); 
      }catch(IOException e){ 
       e.printStackTrace(); 
      } 
     } 
    private static void handleClient(){ 
     try{ 
      String msgIn,msgOut="",senderNick; 
      do{ 
      buffer = new byte[256]; 
      in = new DatagramPacket(buffer,buffer.length); 
      sckt.receive(in); 
      InetAddress clientAddress = in.getAddress(); 
      int clientPort = in.getPort(); 
      msgIn = new String(in.getData(),0,in.getLength()); 
      //print msgIn 
      //System.out.println(msgIn); 
         senderNick = msgIn.substring(0,msgIn.indexOf(" ")); 
         msgIn = msgIn.substring(msgIn.indexOf(" ")+1); 
      if(msgIn.equals("/connect")){ 
       //String nick = msgIn.substring(msgIn.indexOf(" ") + 1); 
       System.out.println(senderNick); 
       if(users.containsKey(senderNick)){ 
        msgOut = "Nick already in use!"; 
       } 
       else{ 
        users.put(senderNick, new User(clientAddress,clientPort)); 
        msgOut = "Connected!"; 
       } 
           sendMsg(clientAddress,clientPort,msgOut); 
      } 
         else if(msgIn.equals("/list")){ 
          Set userNames; 
          userNames = users.keySet(); 
          msgOut = "Users : \n"; 
          msgOut += userNames.toString(); 
          sendMsg(clientAddress,clientPort,msgOut); 
         } 
         else if(msgIn.startsWith("/msg")){ 
          String tmp = msgIn.substring(msgIn.indexOf(" ")+1); 
          String receiverName = tmp.substring(0,tmp.indexOf(" ")); 
          String message = tmp.substring(tmp.indexOf(" ")+1); 

          if(!users.containsKey(receiverName)){ 
           msgOut = "User " + receiverName + " not found!"; 
           sendMsg(clientAddress,clientPort,msgOut); 
          } 
          else{ 
           User receiver = users.get(receiverName); 
           msgOut = "Message from "+ senderNick +" : "+message; 
           sendMsg(clientAddress,clientPort,"Message Sent!"); 
           sendMsg(receiver.addr,receiver.port,msgOut); 
          } 

         } 
         else if(msgIn.startsWith("/nick")){ 
          String newNick = msgIn.substring(msgIn.indexOf(" ")+1); 
          if(users.containsKey(newNick)){ 
           msgOut = "Nick already in use!"; 
          } 
          else{ 
           users.put(newNick,users.get(senderNick)); 
           users.remove(senderNick); 
           msgOut = "Nick changed!"; 
          } 
          sendMsg(clientAddress,clientPort,msgOut); 
         } 
         else if(msgIn.equals("/disconnect")){ 
          users.remove(senderNick); 
         } 

      //out = new DatagramPacket(msgOut.getBytes(),msgOut.length(),clientAddress,clientPort); 
      //sckt.send(out); 
      }while(true); 
     } 
     catch(IOException e){ 
      e.printStackTrace(); 
     } 
     finally{ 
      System.out.println("Closing connection."); 
      sckt.close(); 
     } 
    } 

} 

客戶:

package chat; 

import java.io.*; 
import java.net.*; 
import java.util.Scanner; 

public class Client { 

    private static InetAddress host; 
    private static final int PORT = 27012; 
    private static DatagramSocket sckt; 
    private static DatagramPacket in, out; 
    private static byte[] buffer; 
    private static String nick; 

    static class MessageListener implements Runnable { 
     //DatagramPacket in; 
     //byte[] buffer; 
     String reply; 
     public void run() { 
      do{ 
      try{ 
      buffer = new byte[256]; 
      in = new DatagramPacket(buffer,buffer.length); 
      sckt.receive(in); 
      reply = new String(in.getData(),0,in.getLength()); 
      System.out.println("SERVER> "+reply); 
      } 
      catch(IOException e){ 
       e.printStackTrace(); 
      } 
      }while(true); 
     } 
    } 

    public static void main(String[] args) { 
     try { 
      host = InetAddress.getLocalHost(); 

     } catch (UnknownHostException e) { 
      System.out.println("Host not found!"); 
      System.exit(1); 
     } 
     connect(); 

    } 

    private static void sendMsg(String msg) { 
     try { 
      out = new DatagramPacket(msg.getBytes(), msg.length(), host, PORT); 
      sckt.send(out); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void connect() { 
     Scanner sc = new Scanner(System.in); 

     try { 
      buffer = new byte[256]; 
      sckt = new DatagramSocket(); 
      String reply = ""; 
      do { 
       System.out.println("Name: "); 
       nick = sc.nextLine(); 
       sendMsg(nick + " /connect"); 
       in = new DatagramPacket(buffer, buffer.length); 
       sckt.receive(in); 
       reply = new String(in.getData(), 0, in.getLength()); 
       System.out.println("SERVER> " + reply); 
      } while (!reply.equals("Connected!")); 
      accessServer(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void accessServer() { 
     try { 
      sckt = new DatagramSocket(); 
      Scanner sc = new Scanner(System.in); 
      String msg = "", reply = ""; 
      Thread myT = new Thread(new MessageListener()); 
      myT.start(); 
      do { 
       System.out.print("Enter Message: "); 
       msg = sc.nextLine(); 
       if (!msg.equals("/quit")) { 
        buffer = new byte[256]; 

        sendMsg(nick + " " + msg); 


       } else { 
        sendMsg(nick + " /disconnect"); 
       } 
      } while (!msg.equals("/quit")); 

      sc.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      System.out.println("Connection closing..."); 
      sckt.close(); 
     } 

    } 
} 

我希望能夠將消息發送給單個用戶或所有用戶但問題是我無法在客戶端上收到消息,因爲現在客戶端只會在將消息發送到服務器後收到消息。所以我的想法是使用一個線程連續監聽來自服務器的消息,但它不起作用。最簡單的方法是什麼?

+0

爲什麼你的意思是由線程不起作用? – FDinoff 2013-05-13 21:05:01

+1

看看Netty庫(http://netty.io/) – hoaz 2013-05-13 21:05:39

+0

@FDinoff我對線程沒有任何經驗。我在客戶端有一個MessageListener類,我試圖用它來接收消息:現在,在我的聊天中一切正常,除了當我向另一個用戶發送消息時,另一個用戶沒有得到它。 – Adrian 2013-05-13 21:09:03

回答

1

您試圖立即使用收到的數據報,而不是等待您創建的線程接收數據報並填充您的in變量。您可以直接在線程代碼中處理收到的數據報,或者在使用wait()/ notify()方案接收到數據報時通知主線程。

+0

也可以直接擴展'Thread'。 – 2013-05-13 21:39:32

+0

我現在正在處理線程代碼中收到的消息,它似乎與其他命令一起工作,但是/ msg仍然不起作用。在原始帖子中編輯客戶端代碼。 – Adrian 2013-05-13 21:48:17