2012-08-30 205 views
1

我正在开发一个期望TCP客户端和服务器的项目,其中服务器将消息回显给客户端。以下是从分配:TCP客户端和服务器

服务器应用程序应:

  1. 倾听
  2. 接受连接端口
  3. 从收到的邮件上发起了一个众所周知的IP地址和端口的TCP连接客户端并将它们回显
  4. 继续执行此操作,直到客户端断开连接。

客户机应用程序应:

  1. 建立与在其公知的IP地址和服务器端口
  2. 以异步方式将消息发送到服务器的连接。该消息的格式是您选择的 ;然而,它必须包含足够的信息,以便在从服务器返回时识别它为 。

我已经完成了服务器的编码,这是我想出的客户端。

我的问题:

  • 是什么意思的是服务器侦听一个众所周知的IP和端口我在执行TCP连接,我用ServerSocket它接受端口服务器侦听。我解释正确吗?

  • 在我当前的TCPClient实现中,客户端向服务器发送消息,但println()似乎是一个阻塞调用,这使得它是同步的。我能做些什么来使我的客户端异步?

为了简便起见,我还没有加入TCPSERVER的代码,让我知道,如果需要的话

UPDATE * * 根据反馈,我已经通过的TcpClient类修改。在收到客户请求后,我产生了两个线程ReceiveMessage和SendMessage。这样做,让我以下异常:

[Client] Message sent: Message from Client 97 
[Client] Message sent: Message from Client 98 
[Client] Message sent: Message from Client 99 
[Client] Done Sending all the messages 
java.net.SocketException: Socket closed 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:129) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) 
    at java.io.InputStreamReader.read(InputStreamReader.java:167) 
    at java.io.BufferedReader.fill(BufferedReader.java:136) 
    at java.io.BufferedReader.readLine(BufferedReader.java:299) 
    at java.io.BufferedReader.readLine(BufferedReader.java:362) 
    at org.chanders.client.ReceiveMessage.run(ReceiveMessage.java:18) 
    at java.lang.Thread.run(Thread.java:680) 

以下是新的客户端代码:

public class TCPClient { 
    Socket clientSocket = null; 
    OutputStream out = null; 
    BufferedReader in = null; 
    String message = "Hello from Client"; 
    int messagecount = 100; 

    // server credentials 
    private static final String SERVER_ADDRESS = "localhost"; 
    private static final int SERVER_PORT = 50001; 

    protected void execute() { 
     try { 
      clientSocket = new Socket(SERVER_ADDRESS, SERVER_PORT); 
      Thread send = new Thread(new SendMessage(clientSocket.getOutputStream())); 
      Thread receive = new Thread(new ReceiveMessage(clientSocket.getInputStream())); 

      send.start(); 
      receive.start(); 

      //For server to wait until send and receive threads finish 
      send.join(); 
      receive.join(); 

     } catch (UnknownHostException uhe) { 
      System.err.println("Couldnt find host: " + SERVER_ADDRESS); 
      uhe.printStackTrace(); 
      System.exit(-1); 

     }catch(IOException ioe) { 
      System.err.println("Couldnt get I/O: " + SERVER_ADDRESS); 
      ioe.printStackTrace(); 
      System.exit(-1); 

     }catch(InterruptedException ie) { 
      System.err.println("Thread.join failed: "); 
      ie.printStackTrace(); 
      System.exit(-1); 
     } 
     finally { 
      //cleanup(); 
     } 
    } 

    private void cleanup() { 
     try { 
      clientSocket.close(); 
     }catch(Exception e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } 
    } 

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

public class SendMessage implements Runnable { 
    OutputStream out = null; 
    String message = "Message from Client"; 
    int messageCount = 100; 

    public SendMessage(OutputStream out) { 
     this.out = out; 
    } 

    public void run() { 
     PrintWriter writer = new PrintWriter(out); 
     try { 

      for (int i = 0; i < messageCount; i++) { 
       String m = message + " " + i; 
       writer.println(m); 
       System.out.println("[Client] Message sent: " + m); 
      } 
      System.out.println("[Client] Done Sending all the messages"); 

     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } finally { 
      cleanup(); 
     } 

    } 
    private void cleanup() { 
     try { 
      out.close(); 
     }catch(Exception e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } 
    } 
} 

public class ReceiveMessage implements Runnable { 
    InputStream in = null; 
    String message; 

    public ReceiveMessage(InputStream in) { 
     this.in = in; 
    } 

    public void run() { 
     BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
     try { 

      while ((message = reader.readLine()) != null) { 

       System.out.println("[Client] Received message from Server: " 
         + message); 
      } 

      System.out.println("[Client] Done Receiving messages from Server"); 

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

    } 
    private void cleanup() { 
     try { 
      in.close(); 
     }catch(Exception e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } 
    } 
} 

回答

0

使用一个单独的线程为每个客户端。当你写一些东西时,在服务器端,必须有一个接受字符串的方法。否则它会被阻止。粘贴您的服务器代码。

+0

这个问题似乎是关于如何使它异步。 – vsz

1

在这种情况下,Asynchronous可能并不意味着您不能使用println,但客户端必须能够在发送新消息时接收消息。 客户端应创建套接字,然后创建两个线程,一个发送消息,另一个线程收回并打印它们。

更新

为避免该异常,使用clientSocket.shutdownOutput()的,而不是关闭输出流。 你可以移动发送代码回主线程,并保持了一个单独的线程接收代码或加入发送线程之后,调用shutdownOutput()。无论什么对你更好。

+0

我已经根据你的建议修改了代码。 –

0

众所周知的端口是专门为特定协议指定的端口号,例如80代表HTTP,443代表HTTPS。你打算执行一个特定的协议吗?如果你是我建议你使用该协议的端口号。维基百科有这里众所周知的端口号的列表: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

0

如果这是一个专业的分配(而不是一个点功课),那么我会强烈建议Netty Server,这基本上是一个NIO客户端服务器架构。它显着简化/简化了这种发展。

请务必检查他们的documentation,因为它提供了实现问题中所述服务器/客户端功能的示例。

如果这是一项家庭作业,则this example应提供所有必要的细节。请检查Oracle resources

+0

它的功课。我不需要使用外部框架。 –

+0

已添加指向相关示例集的链接。 – 01es