自定义Java套接字类

时间:2015-05-27 03:16:21

标签: java sockets serversocket

这是我第一次搞乱套接字,直到现在还在努力。基本上,我有一个名为ServerSocket的自定义Server类和一个名为Socket的自定义Client类。

当客户端尝试连接到服务器时,服务器执行一些检查以确保它实际上是客户端尝试建立连接,而不是其他套接字,因为客户端具有我需要的某些方法。

但是,此检查始终返回false。这是我的服务器连接代码:

package me.eli.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import me.eli.client.Client;

public class Server extends ServerSocket {

private final Map<Client, IOPair> clients = new HashMap<Client, IOPair>();

public Server(final int port) throws IOException {
    super(port);
    System.out.println("Server started on " + getLocalPort() + "... Waiting for client!");
}

public Client waitOnClient() throws IOException {
    final Socket generalClient = accept();
    final Client client;
    if(!(generalClient instanceof Client)) {
        client = null;
        PrintWriter out = new PrintWriter(generalClient.getOutputStream(), true);
        out.println("Access denied: " + generalClient.getClass().getSimpleName());
        log("Invalid client: " + generalClient.getClass().getName() + " (" + generalClient.getInetAddress().getHostAddress() + ")");
        out.close();
    } else
        client = (Client) generalClient;
    if(client == null)
        return null;
    client.setServer(this);
    BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
    PrintWriter out = new PrintWriter(client.getOutputStream(), true);
    broadcast(client.getName() + " has joined.");
    clients.put(client, new IOPair(in, out));
    System.out.println("Client (" + client.getName() + ") connected from " + client.getInetAddress().getHostAddress());
    out.println("Connected! Welcome to the server.");
    return client;
}

@Override
public void close() throws IOException {
    for(Client c : getClients())
        kick(c, "Server closed");
    super.close();
}

public void kick(Client c, String reason) {
    try {
        c.message("disconnect", reason);
        c.close();
    } catch(IOException e) {
        log("Failed to kick " + c.getName() + ": " + e.getMessage());
        c.message("error", "Failed to disconnect");
    }
}

public void log(String message) {
    getServerOut().println(message);
}

public void log(String source, String message) {
    log("<" + source + "> " + message);
}

public void broadcast(String message) {
    log("broadcast", message);
    for(Client c : getClients())
        c.message("broadcast", message);
}

public Client[] getClients() {
    return clients.keySet().toArray(new Client[clients.keySet().size()]);
}

public BufferedReader getClientIn(Client c) {
    return clients.get(c).getIn();
}

public PrintWriter getClientOut(Client c) {
    return clients.get(c).getOut();
}


public InputStream getServerIn() {
    return System.in;
}

public PrintStream getServerOut() {
    return System.out;
}

public static boolean isServerRunningOn(final int port) {
    try {
        new ServerSocket(port).close();
        return false;
    } catch(IOException e) {
        return true;
    }
}

}

这是我的客户端连接代码:

package me.eli.client;

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

import me.eli.server.IOPair;
import me.eli.server.Server;

public class Client extends Socket {

private Server server;
private final IOPair serverio;
private final String name;

public Client(final String host, final int port) throws IOException {
    this(host, port, "Guest-" + (int) (Math.random() * 10000));
}

public Client(final String host, final int port, final String name) throws IOException {
    super(host, port);
    System.out.println("Connected to server on " + host + ":" + port);
    BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
    PrintWriter out = new PrintWriter(getOutputStream(), true);
    this.name = name;
    this.serverio = new IOPair(in, out);
    String input;
    if((input = in.readLine()) != null)
        System.out.println("<Welcome message> " + input);
    out.println("Yay! I'm connected!");
}

@Override
public synchronized void close() throws IOException {
    if(serverio != null) {
        if(server != null)
            server.broadcast(getName() + " has disconnected.");
        message("server", "Disconnected.");
        super.close();
        serverio.getIn().close();
        serverio.getOut().close();
    } else
        super.close();
}

public void message(String source, String message) {
    getClientOut().println("<" + source + "> " + message);
}

public String getName() {
    return name;
}

public void setServer(Server server) {
    this.server = server;
}

public Server getServer() {
    return server;
}

public BufferedReader getServerIn() {
    return serverio.getIn();
}

public PrintWriter getServerOut() {
    return serverio.getOut();
}

public InputStream getClientIn() {
    return System.in;
}

public PrintStream getClientOut() {
    return System.out;
}

}

我不是最有经验的网络,但这让我感到困惑,因为我确实连接了我的Client类。提前谢谢!

1 个答案:

答案 0 :(得分:2)

  

服务器执行一些检查以确保它实际上是客户端,它尝试建立连接

不可能和荒谬。 Client类位于连接的另一端。它并没有神奇地传输到您的accept()方法。如果要验证客户端,则必须在应用程序协议中构建一些内容。

注意:

  • 调用Client.setServer()同样徒劳无功。它并没有神奇地传递给客户。
  • 可以让您的ServerSocket派生类在其Client方法中创建Socket个对象而非accept()个对象,但实际上并非如此解决你试图解决的问题。