Java套接字服务器无响应

时间:2015-12-05 16:40:01

标签: java eclipse sockets

我刚从好奇心开始使用Java套接字。

我写了一小段代码,一个服务器和一个客户端。

服务器接受一个字符串并将其转换为大写字母并返回给客户端。

我希望服务器能够处理多个客户端并具有持久连接。

这是服务器代码:

package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;

public class Server {

    private ServerSocket listener;
    private ArrayList<Socket> clients;

    public Server() throws IOException{
        clients = new ArrayList<Socket>();
        listener = new ServerSocket(7575);
    }

    public Server(int port) throws IOException{
        clients = new ArrayList<Socket>();
        listener = new ServerSocket(port);
    }

    public void start() throws IOException, InterruptedException{

        Thread one = new Thread(){

            public void run(){
                while (true){
                    Socket socket = null;
                    try {
                        socket = listener.accept();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    if (socket.isConnected()){
                        try {
                            socket.setKeepAlive(true);
                        } catch (SocketException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        clients.add(socket);
                        System.out.println(socket.getRemoteSocketAddress().toString());
                    }
                }
            }
        };

        Thread two = new Thread(){
            public void run(){
                try {
                    while (true){
                        work();
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        };

        one.start();
        two.start();

        one.join();
        two.join();

        stop();
    }

    private void stop() throws IOException{
        listener.close();
    }

    private void work() throws IOException{
        if (clients.size() == 0){
            return;
        }
        for(int i = 0; i < clients.size(); i++){
            Socket socket = clients.get(i);
            if (!socket.isClosed()){
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                String data = br.readLine();
                if (data == null) continue;
                out.println(data.toUpperCase());
            }
            else{
                clients.remove(socket);
            }
        }
    }
}

package entry;

import java.io.IOException;

import server.Server;

public class Main {
    public static void main(String args[]) throws IOException{
        Server server = new Server();
        try {
            server.start();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这是客户:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Main {
    public static void main(String args[])throws IOException{
        Socket socket = new Socket("192.168.0.110", 7575);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        BufferedReader sr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter pr = new PrintWriter(socket.getOutputStream(), true);

        while (true){
            System.out.println("\n\nEnter a string : ");
            String inp = br.readLine();
            if (inp.equals("quit")) break;
            pr.println(inp);
            System.out.println("The response is : " + sr.readLine());
        }
        socket.close();
    }
}

奇怪的是,当我在服务器代码中设置断点并逐步执行eclipse中的代码时,代码完全按预期工作,即我在客户端获得响应。

但是当我直接在eclipse中运行它时,我没有得到客户端的响应。

无法理解出了什么问题。

修改

我似乎解决了这个问题。

以下是代码段:

Thread two = new Thread(){
            public void run(){
                try {
                    while (true){
                        Thread.sleep(1000); //This is the added line
                        work();
                    }
                } catch (IOException | InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        };

但是我仍然对于什么使时间差异感到困惑。 有没有更清洁的方法来实现这一目标?

2 个答案:

答案 0 :(得分:1)

我用不同的方法解决了这个问题。

以下是新方法:

ServerHandler.java:

package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;

public class ServerHandler extends Thread{
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    private ArrayList<Socket> clients;

    public ServerHandler(Socket socket) throws IOException{
        this.socket = socket;
        clients = new ArrayList<Socket>();
        if (!clients.contains(socket)){
            clients.add(this.socket);
            System.out.println(this.socket.getRemoteSocketAddress());
        }
    }

    @Override
    public void run(){
        while (true){
            if (clients.isEmpty()) break;
            String str = null;
            for (int i = 0; i < clients.size(); i++){
                Socket socket = clients.get(i);
                if (socket.isClosed()){
                    clients.remove(socket);
                    continue;
                }
                try {
                    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                } catch (IOException e2) {
                    // TODO Auto-generated catch block
                    e2.printStackTrace();
                }
                try {
                    out = new PrintWriter(socket.getOutputStream(), true);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                try {
                    str = in.readLine();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                out.println(str.toUpperCase());
            }
        }
    }
}

Main.java [用于运行服务器]:

package entry;

import java.io.IOException;
import java.net.ServerSocket;

import server.ServerHandler;

public class Main {
    public static void main(String args[]) throws IOException{
        ServerSocket listener = new ServerSocket(7575);
        try{
            while (true){
                new ServerHandler(listener.accept()).start();
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
        finally{
            listener.close();
        }
    }
}

答案 1 :(得分:1)

好的,我们走了。我不理解使用Arraylist来维护连接,除非您正在处理每个Client的混乱细节。
一次处理多个客户端的最常用或首选方法可以通过示例来理解:

Server.java

import java.net.ServerSocket;
import java.io.IOException;

class Server {
    public static void main(String[] args) throws IOException {
        try( ServerSocket ss =  new ServerSocket(3333)) { // try with resources
            new ServerThread(ss.accept()).start();
        }
    }
}

正如您所看到的,我刚刚定义了一个将侦听客户端连接的类,并且一旦向服务器发出请求,它将启动一个在下一个类中定义的Thread。这里要注意的一点是使用Try-with-Resources块。任何实现Closeable接口的类都可以包含在此try语句中。 try-with-resources会自动为我关闭流或连接。这意味着,您从代码中删除了所有冗余的try-catch块,并改为使用此try

现在,

ServerThread.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;


public class ServerThread extends Thread {
    Socket s = null;

    public ServerThread(Socket s) {
        super("ServerThread");
        this.s = s;
    }

    public void run() {
        try( PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
                BufferedReader stream = new BufferedReader(new InputStreamReader(s.getInputStream()));
                            BufferedReader write = new BufferedReader(new InputStreamReader(System.in))) {
            System.out.println("In Server");
            String in, out;
            while ((in = stream.readLine()) != null) {
                System.out.println("Msg 4m client: " + in);
                if(in.equals("bye"))
                    break;
                out = write.readLine();
                pw.println(out);
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

在这里观察try-with-resources语句,我们可以在这里初始化多个Connections / Input-Output Streams,一旦编译器从try语句返回,所有打开的连接将自动关闭.Also ,观察while语句,它将一直运行直到客户端发送消息,并且如果消息是"bye"则退出。

最后,一个向服务器发送请求的客户端程序。

Client.java

import java.net.Socket;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

class Client {
    public static void main(String[] args) {
        try( Socket s = new Socket("localhost", 3333); 
                PrintWriter pw = new PrintWriter(s.getOutputStream(), true); 
                    BufferedReader stream = new BufferedReader(new InputStreamReader(s.getInputStream())); 
                        BufferedReader write = new BufferedReader(new InputStreamReader(System.in)) ) {
            System.out.println("In Client");
            String in;
            while ((in = write.readLine()) != null) {                
                pw.println(in);
                if(in.equals("bye"))
                    break;
                System.out.println("Msg 4m server: " + stream.readLine());
            }
        } catch(IOException e) {
            System.err.println("Exception: " + e);
        }
    }
}

注意,这里的while语句将循环直到用户输入消息,如果消息是&#34; bye&#34;,它将退出。程序的恢复可以很容易理解从上面的解释。