Java Simple EchoServer无法运行

时间:2014-06-18 19:21:14

标签: java

我经常阅读了很多内容,并且发现了许多正在做我想做的事情的例子。但我根本无法在我的代码中找到问题。可能我只需要一双新的眼睛来看我的代码。    因此,存在被标记为重复线程的风险。我有一个简单的Java代码。它打开一个端口。将套接字连接到该套接字。获取输入流和输出流。将一些文本放入输出流,输入流尝试读取文本。当执行readLine的mehtod时,它不会返回到代码。它只是继续运行,永远不会回到主方法。

import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;

public class echoserver {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    String hostName = "127.0.0.1";
    //      InetAddress.getLocalHost()
    int portNumber = 5000;
    ServerSocket ss = null;
    Socket echoSocket = null;


    try {
        ss = new ServerSocket(portNumber);
        echoSocket = new Socket(hostName, portNumber);
//          echoSocket = ss.accept();
        System.out.println("open");
        System.out.println(echoSocket.isBound());

        PrintWriter writer = new PrintWriter(echoSocket.getOutputStream());
        for (int i = 0; i < 100; i++) {
            writer.print("test String");    
        }

        writer.flush();
//          writer.close();

        System.out.println("inputstream read");
       DataInputStream is = new DataInputStream(echoSocket.getInputStream());
       String fromStream = is.readLine();
       System.out.println(fromStream);

       System.out.println("bufferreader read");

        BufferedReader reader = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
        String fromReader = reader.readLine();

        System.out.println(fromReader);

    } catch (UnknownHostException  ex1) {
        // TODO Auto-generated catch block
        System.out.println("EX1");
        ex1.printStackTrace();
    }

    catch (IOException ex2) {
        // TODO: handle exception
        System.out.println("EX2");
        ex2.printStackTrace();
    }

    finally {
        try {
            echoSocket.close();
            ss.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }



}

}

编辑:下面更新的代码...此代码中唯一的问题是Server.Run中的while循环永远不会结束。我寻找其他一些属性(我记得像isTextAvailable这样的东西),却找不到它。代码背后的想法是将其转换为聊天客户端。不用说它的斗争!

编辑2:我发现了这个问题。我从来没有从作家端关闭套接字,所以列表工作者继续听!谢谢大家的帮助!

clientsocket.close();

添加了一行,然后就可以了!

import java.net.*;
import java.io.*;
import java.io.ObjectInputStream.GetField;
import java.util.*;

public class echoserver {



static echoserver echo;

public static class Client implements Runnable {

    Socket clientsocket;
    String hostName = "127.0.0.1";
    int portNumber = 5000;
    static int onesleep = 0;

    public void run(){ 


        System.out.println("Client Run  " + new Date());

        try {
            clientsocket = new Socket(hostName,portNumber);
            PrintWriter writer = new PrintWriter(clientsocket.getOutputStream());

            for (int i = 0; i < 10; i++) {
                writer.println("test String   " + i );  
            }

            writer.flush();
                            clientsocket.close();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



    }
}

public class Server implements Runnable {

    public void run(){

        System.out.println("Server Run" + new Date());
        int portNumber = 5000;
        ServerSocket ss = null;
        Socket serversocket = null;
        InputStreamReader streamReader; 

        try {
            ss = new ServerSocket(portNumber);
            serversocket = ss.accept();

            System.out.println("bufferreader read  " + new Date());

            streamReader = new InputStreamReader(serversocket.getInputStream());
            BufferedReader reader = new BufferedReader(streamReader);
            String fromReader;

            System.out.println(reader.ready());
            System.out.println(reader.readLine());



            while ((fromReader = reader.readLine()) != null) {
                System.out.println(fromReader);

            }

            System.out.println("After While in Server Run");


        } catch (IOException ex_server) {
            // TODO Auto-generated catch block
            System.out.println("Server Run Error    " + new Date());
            ex_server.printStackTrace();

        }
          finally {
              try {
                serversocket.close();
                  ss.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

          }
        System.out.println("open" + new Date());
        System.out.println(serversocket.isBound());


    }
}


public void go(){

    Server server = new Server();
    Thread serverThread = new Thread(server);
    serverThread.start();

    Client client = new Client();
    Thread clientThread = new Thread(client);
    clientThread.start();

}

public static void main(String[] args) {
    // TODO Auto-generated method stub

    echo = new echoserver();
    echo.go();





}

}

2 个答案:

答案 0 :(得分:4)

我之前准备了这篇文章的一个版本,但根据你在另一个答案中的最后评论,似乎你已经弄明白了。无论如何我会张贴这个,以防它有任何帮助。

广泛的答案是,您的类,就像您目前拥有它一样,有效地代表同一线程/进程中的客户端和服务器端部分。如您所见,您可以将数据写入出站(或客户端)套接字,但服务器端组件永远不会有机会侦听传入连接。

因此,当您尝试从入站(或服务器端)套接字的输入流中读取数据时,不存在任何内容,因为没有收到任何内容。 readline()方法最终会阻塞,直到数据可用,这就是为什么您的程序似乎保持在那一点。另外,就像haifzhan所说的那样,使用new Socket(...)创建一个新的套接字并不能建立连接,你所拥有的只是一个没有流的套接字。

ServerSocket#accept方法,您需要使用什么来监听连接。此方法将为您创建套接字,您可以从中尝试从其流中读取。就像haifzhan所说,该方法会阻塞,直到建立连接,这最终导致它无法在单线程环境中正常运行。

要在同一个应用程序中执行此操作,您只需要分离组件并在单独的线程中运行它们。尝试以下内容:

public class EchoClient {

    public static void main(String[] args) throws InterruptedException {
        new Thread(new EchoServer()).start(); // start up the server thread

        String hostName = "localhost";
        int portNumber = 5000;

        try {
            Socket outboundSocket = new Socket(hostName, portNumber);

            System.out.println("Echo client is about to send data to the server...");

            PrintWriter writer = new PrintWriter(outboundSocket.getOutputStream());
            for (int i = 0; i < 100; i++) {
                writer.print("test String");
            }

            System.out.println("Data has been sent");

            writer.flush();
            outboundSocket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器组件,作为单独的线程运行:

public class EchoServer implements Runnable {

    public void run(){
        try {
            ServerSocket ss = new ServerSocket(5000);
            System.out.println("Waiting for connection...");
            Socket inboundSocket = ss.accept();

            System.out.println("inputstream read");
            DataInputStream is = new DataInputStream(inboundSocket.getInputStream());

            BufferedReader reader = new BufferedReader(new InputStreamReader(is));

            String fromStream = reader.readLine();
            System.out.println(fromStream);

            System.out.println("bufferreader read");
            ss.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

答案 1 :(得分:2)

您没有连接到任何客户端套接字......

来自Writing the Server Side of a socket

  

accept方法等待客户端启动并请求a   此服务器的主机和端口上的连接。连接时   请求并成功建立,accept方法返回一个   新的Socket对象绑定到同一本地端口并具有其   远程地址和远程端口设置为客户端的地址。服务器   可以通过这个新的Socket与客户端进行通信并继续   在原始ServerSocket上侦听客户端连接请求。

ss = new ServerSocket(portNumber);
echoSocket = new Socket(hostName, portNumber)
// echoSocket = ss.accept();

您不应该使用新的Socket(主机,端口)来创建echoSocket,ss.accept()是建立服务器客户端连接的正确方法。

由于上面的代码(echoSocekt = ss.accept();)不正确而挂起的原因因此以下内容无法使用

DataInputStream is = new DataInputStream(echoSocket.getInputStream());

如果调用is.available(),它将返回0,这意味着可以读取0个字节。

阅读我提供的链接,检查EchoServer.java和EchoClient.java,您将建立自己的连接