自定义 Java 套接字 class

Custom Java Socket class

这是我第一次弄乱套接字,一直到现在。基本上,我有一个名为 Server 的自定义 ServerSocket class 和一个名为 Client.

的自定义 Socket class

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

然而,这个检查总是returns错误。这是我的服务器连接代码:

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;
}

}

我不是最有网络经验的,但这让我感到困惑,因为我确实与我的客户联系 class。提前致谢!

Server performs a little check to make sure it is actually Client that it trying to make the connection

不可能和荒谬。 Client class 在连接的另一端。它不会神奇地传输到您的 accept() 方法。如果你想验证你的客户端,你必须在你的应用程序协议中构建一些东西。

备注:

  • 调用Client.setServer()同样是徒劳的。它不是神奇地传送到客户端。
  • 可以让您的 ServerSocket 派生的 class 在其 accept() 方法中创建 Client 对象而不是 Socket 对象,但是实际上并没有解决您要解决的问题。