首页 > 解决方案 > 将具有不同 IP 的多个客户端模拟到服务器套接字

问题描述

我有一个接受多个客户端的服务器套接字应用程序。我想用java编写客户端应用程序,将请求发送到服务器应用程序。有什么方法可以模拟具有不同 IP 的多个客户端到服务器应用程序

谢谢,维诺迪尼。

标签: javasockets

解决方案


请检查以下方法是否对您有帮助?

我已经在同一台机器上验证了 Linux 上的解决方案。

我的 Linux 机器只有一个 NIC(网络接口卡)。

/sbin/ifconfig

eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:10.x.x.x  Bcast:x.x.x.x  Mask:255.255.x.xx

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.x.x.x

我已经暂时给这个网卡添加了多个 IP 地址

您可以使用“ifconfig”命令将 IP 地址添加到 NIC。但请注意,重启机器后该 IP 地址将不可用。在这里,我们假设您已经有一个配置了静态 IP 的 NIC。如果我们需要再添加两个 IP 地址,比如 192.168.1.25 和 192.168.1.26 到这个接口,我们可以通过以 root 用户执行以下命令来完成:

ifconfig eth0:1 192.168.1.25 netmask 255.255.255.0
ifconfig eth0:2 192.168.1.26 netmask 255.255.255.0

帖子补充:

/sbin/ifconfig

eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:10.x.x.x  Bcast:x.x.x.x  Mask:255.255.x.xx

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.x.x.x
          
eth0:1    Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:192.168.1.25  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

eth0:2    Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:192.168.1.27  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

现在我的 Linux 主机有 2 个额外的临时 IP 地址。

我在我的 Linux 机器上运行以下服务器套接字程序

远程文件服务器.java

package socket.learning;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;

public class RemoteFileServer {
    public static void main(String[] args) {
        RemoteFileServer server = new RemoteFileServer();
        server.acceptConnections(Integer.parseInt(args[0]));
    }

    public void acceptConnections(int listenPort) {
        try {
            ServerSocket server = new ServerSocket(listenPort);
            Socket incomingConnection = null;
            while (true) {
                incomingConnection = server.accept();
                handleConnection(incomingConnection);
            }
        } catch (BindException e) {
            System.out.println("Unable to bind to port " + listenPort);
        } catch (IOException e) {
            System.out.println("Unable to instantiate a ServerSocket on port: "
                    + listenPort);
        }
    }

    public void handleConnection(Socket incomingConnection) {
        try {
            System.out.println("Client socket details:  getInetAddress  "
                    + incomingConnection.getInetAddress()
                    + "    getLocalAddress  "
                    + incomingConnection.getLocalAddress()
                    + "   getRemoteSocketAddress  "
                    + incomingConnection.getRemoteSocketAddress());
            OutputStream outputToSocket = incomingConnection.getOutputStream();

            InputStream inputFromSocket = incomingConnection.getInputStream();
            BufferedReader streamReader = new BufferedReader(
                    new InputStreamReader(inputFromSocket));
            String fileName = streamReader.readLine();
            FileReader fileReader = new FileReader(new File(fileName));
            BufferedReader bufferedFileReader = new BufferedReader(fileReader);
            PrintWriter streamWriter = new PrintWriter(outputToSocket);
            String line = null;
            while ((line = bufferedFileReader.readLine()) != null) {
                streamWriter.println(line);
            }
            fileReader.close();
            streamWriter.close();
            streamReader.close();
        } catch (Exception e) {
            System.out.println("Error handling a client: " + e);
        }
    }
}

执行:

java -cp .  socket/learning/RemoteFileServer 9999

9999 是服务器套接字绑定/监听端口。

在我的 Linux 机器上运行以下客户端套接字程序

使用以下 Socket 构造函数将客户端套接字绑定到本地地址

public Socket(InetAddress address,
      int port,
      InetAddress localAddr,
      int localPort)
       throws IOException
Creates a socket and connects it to the specified remote address on the specified remote port. The Socket will also bind() to the local address and port supplied.
If the specified local address is null it is the equivalent of specifying the address as the AnyLocal address (see InetAddress.isAnyLocalAddress()).

A local port number of zero will let the system pick up a free port in the bind operation.

If there is a security manager, its checkConnect method is called with the host address and port as its arguments. This could result in a SecurityException.

Parameters:
address - the remote address
port - the remote port
localAddr - the local address the socket is bound to, or null for the anyLocal address.
localPort - the local port the socket is bound to or zero for a system selected free port.

远程文件客户端.java

package socket.learning;

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

public class RemoteFileClient {
    protected String hostIP;
    protected int hostPort;
    protected BufferedReader socketReader;
    protected PrintWriter socketWriter;

    public RemoteFileClient(String hostIP, int hostPort) {
        this.hostIP = hostIP;
        this.hostPort = hostPort;
    }

    public static void main(String[] args) {
        RemoteFileClient remoteFileClient = new RemoteFileClient(args[0],
                Integer.parseInt(args[1]));
        remoteFileClient.setUpConnection(args[3]);
        String fileContents = remoteFileClient.getFile(args[2]);
        remoteFileClient.tearDownConnection();
        System.out.println(fileContents);
    }

    public void setUpConnection(String clientIpAddress) {
        try {
            Socket client = new Socket(hostIP, hostPort,
                    InetAddress.getByName(clientIpAddress), 0);
            socketReader = new BufferedReader(new InputStreamReader(
                    client.getInputStream()));
            socketWriter = new PrintWriter(client.getOutputStream());
        } catch (UnknownHostException e) {
            System.out
            .println("Error setting up socket connection: unknown host at "
                    + hostIP);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Error setting up socket connection: " + e);
        }
    }

    public String getFile(String fileNameToGet) {
        StringBuffer fileLines = new StringBuffer();
        try {
            socketWriter.println(fileNameToGet);
            socketWriter.flush();
            String line = null;
            while ((line = socketReader.readLine()) != null)
                fileLines.append(line + "\n");
        } catch (IOException e) {
            System.out.println("Error reading from file: " + fileNameToGet);
        }
        return fileLines.toString();
    }

    public void tearDownConnection() {
        try {
            socketWriter.close();
            socketReader.close();
        } catch (IOException e) {
            System.out.println("Error tearing down socket connection: " + e);
        }
    }
}

执行:

java -cp .  socket/learning/RemoteFileClient 10.x.x.x 9999 /tmp/test.log 192.168.1.27
java -cp .  socket/learning/RemoteFileClient 10.x.x.x 9999 /tmp/test.log 192.168.1.25
java -cp .  socket/learning/RemoteFileClient 10.x.x.x 9999 /tmp/test.log 10.x.x.x
java -cp .  socket/learning/RemoteFileClient 10.x.x.x 9999 /tmp/test.log 127.0.0.1

对应的服务器控制台输出:

Client socket details:  getInetAddress  /192.168.1.27    getLocalAddress  /10.x.x.x   getRemoteSocketAddress  /192.168.1.27:14774
Client socket details:  getInetAddress  /192.168.1.25    getLocalAddress  /10.x.x.x   getRemoteSocketAddress  /192.168.1.25:29188
Client socket details:  getInetAddress  /10.x.x.x    getLocalAddress  /10.x.x.x   getRemoteSocketAddress  /10.x.x.x:42407
Client socket details:  getInetAddress  /127.0.0.1    getLocalAddress  /10.x.x.x   getRemoteSocketAddress  /127.0.0.1:36002

推荐阅读