有没有可能从不同的类中的同一端口编写/读取套接字?

huangapple go评论64阅读模式
英文:

Is there a possiblity to write/read from a socket on same port from different class

问题

我有一个用于机器之间通信的Spring Boot应用程序(tcp客户端)和TCP服务器(localhost)。我可以与一个机器/客户端通信,但无法与两个或更多机器通信。
因此,我启动了我的Spring Boot应用程序:

package com.example.workflow;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.IOException;

@SpringBootApplication
public class Application {

  public static void main(String[] args) throws IOException {

    Runnable serverZyklisch = new ServerZyklisch();
    Runnable serverAzyklisch = new ServerAzyklisch();
    for (int i = 0; i < 4; i++) {
      new Thread(serverZyklisch).start();
      new Thread(serverAzyklisch).start();
    }
    SpringApplication.run(Application.class);
  }
}

在这里,我启动了不同的线程,以便客户端(例如10.50.12.174 = Press,10.50.12.204 = Drill)可以通过Socket连接连接到TCP服务器。

我的ServerAzyklisch类如下所示:

package com.example.workflow;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerAzyklisch implements Runnable, JavaDelegate {
    // ... 这里省略了类的其余部分 ...
}

现在,我想将“while循环”(带有out.write)从其他类中分离出来,以便像在ServerAzyklisch的run方法中一样使用与Socket的连接。

因此,我编写了一个类Presse.java:

package com.example.workflow;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Presse implements JavaDelegate {
    // ... 这里省略了类的其余部分 ...
}

我想从这个类发送我的3条消息,就像在ServerAzyklisch类中一样。但是它抛出错误,原因是:

Caused by: java.net.BindException: Address already in use: NET_Bind

我知道这是因为我第二次执行Socket.accept,但我不明白我如何使其正常工作。我是否必须关闭Socket连接?如果是的话,在哪里以及使用哪个Java命令来关闭?

英文:

Im having Spring Boot Application for communication between Machines (tcp Clients) and TCP Server (localhost). I am able to communicate with one machine/client, but I cant communicate with 2 or more machines.
Therefore I start my Spring Boot Application:

package com.example.workflow;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.IOException;

@SpringBootApplication
public class Application {

  public static void main(String[] args) throws IOException {

    Runnable serverZyklisch = new ServerZyklisch();
    Runnable serverAzyklisch = new ServerAzyklisch();
    for (int i = 0; i &lt; 4; i++) {
      new Thread(serverZyklisch).start();
      new Thread(serverAzyklisch).start();
    }
    SpringApplication.run(Application.class);
  }
}

There I have different Threads started, so that the clients (for example 10.50.12.174 = Press, 10.50.12.204 = Drill) can connect to TCP Server over Socket Connection.

My ServerAzyklisch class is like this:

package com.example.workflow;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerAzyklisch implements Runnable, JavaDelegate {
    int count = 0;
    private final ServerSocket ssocket;
    static String param = StartTCPServersDelegate.parameter;
    HexToByteConverter hexToByteConverter = new HexToByteConverter();
    // 2 TCP Server starten Port 2000, Port 2001
    public ServerAzyklisch(String Pparam) throws IOException {
        ssocket = new ServerSocket(2000);
        param = Pparam;
    }

    public ServerAzyklisch() throws IOException {
        ssocket = new ServerSocket(2000);
    }

    public void run() {
        byte[] buf = new byte[1];
        System.out.println(param+&quot;Paraaam&quot;);
        InputStream in;
        OutputStream out = null;
        Socket socket = null;
        //Thread immer aktiv
        int n = 0;
        while(true){
            try {
                // Wartet auf Socket Verbindung
                System.out.println(&quot;Server is listening on port &quot;+ ssocket.getLocalPort());
                socket = ssocket.accept();
                count++;
                System.out.println(&quot;Countet clients: &quot;+count);
                socket.setSoLinger(true, 1000);
                System.out.println(&quot;Sockeport: &quot;+socket.getLocalPort());
                System.out.println(&quot;Connection from &quot; + socket.getInetAddress().toString());
                //Inputstream
                in = socket.getInputStream();
                //Outputstream
                out = socket.getOutputStream();
                //Datenpuffer deklarieren (anlegen)
                byte []data = new byte[132];
                               
                byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray(&quot;33333333003d0064000600000004004001c9c78900010000006e0000000000000000000000000001000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;+param);
                byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray(&quot;3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;);
                byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray(&quot;3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;);
                                                
                in.read(buf);
                while (buf[0] != -1) {
                    out.write(Pressen1hexdump110);
                    out.write(Pressen2hexdump);
                    out.write(Pressen3hexdump);
                    }
               
            } catch (IOException e) {
                e.printStackTrace();
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    @Override
    public void execute(DelegateExecution delegateExecution) throws IOException {
        
    }
}

Now I want to outsource the "while loop" (with out.write) in other Classes to use the connection to Socket like in ServerAzyklisch run method.

Therefore I wrote for example a Class Presse.java

package com.example.workflow;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Presse implements JavaDelegate {

    ServerSocket ssocket;
    private HexToByteConverter hexToByteConverter = new HexToByteConverter();
    Socket socket;
    InputStream in;
    OutputStream out;

    byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray(&quot;33333333003d0064000600000004004001c9c78900010000006e00000000000000000000000000010000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005&quot;);
    byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray(&quot;3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;);
    byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray(&quot;3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;);


    public Presse() throws IOException {
        ssocket = new ServerSocket(2000);
        socket = ssocket.accept();
        //Inputstream
        in = socket.getInputStream();
        //Outputstream
        out = socket.getOutputStream();
    }

    public void sendMessage(InputStream in, OutputStream out, byte[]message) throws IOException {
        out.write(Pressen1hexdump110);
        out.write(Pressen2hexdump);
        out.write(Pressen3hexdump);
        socket.close();
    }

    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
        PostRequestDelegate postRequestDelegate = new PostRequestDelegate();
        postRequestDelegate.post();
    }
}

I want to send my 3 messages from this class, like in ServerAzyklisch class. But it throws Error because:

Caused by: java.net.BindException: Address already in use: NET_Bind

I know this because is I do Socket.accept a second time, but I dont understand how I can achieve this to work. Do I have to close socket connection ? If yes where and with which Java Command ?

答案1

得分: 0

如果您希望在程序中拥有多个“Presse”实例,至少需要从其中删除ServerSocket。相反,您应该在其他地方accept来自客户端的连接,并将客户端套接字传递给Presse构造函数:

public Presse(Socket clientSocket) throws IOException {
    this.socket = clientSocket;
    // 输入流
    in = socket.getInputStream();
    // 输出流
    out = socket.getOutputStream();
}

通常,您只希望创建一个 ServerSocket,并在循环中调用accept。为了允许多个客户端同时连接,可以在单独的线程中与客户端通信。这样,服务器就可以继续接受新的连接。以下是如何使用线程池的示例骨架:

int maxClients = 10;
ExecutorService threadPool = Executors.newFixedThreadPool(maxClients);
ServerSocket serverSocket = new ServerSocket(2000);
while (true) {
    Socket clientSocket = serverSocket.accept();
    threadPool.submit(() -> {
        // 与 clientSocket 通信,例如:
        Presse p = new Presse(clientSocket);
        // 您可能希望将此代码放在一个单独的方法中
    });
}
英文:

If you want to have more than one instances of "Presse" in your program, the very least you'll need to remove ServerSocket from it. Instead, you should accept the connection from the client somewhere else, and pass the client socket to the Presse constructor:

public Presse(Socket clientSocket) throws IOException {
    this.socket = clientSocket;
    //Inputstream
    in = socket.getInputStream();
    //Outputstream
    out = socket.getOutputStream();
}

Usually you want to create only one ServerSocket, and call accept on it in a loop. To allow more than one client to connect at a time, communicate with the client in a separate thread. This way the server can go and accept a new connection. Here's a skeleton example of how to use a thread pool for this:

int maxClients = 10;
ExecutorService threadPool = Executors.newFixedThreadPool(maxClients);
ServerSocket serverSocket = new ServerSocket(2000);
while (true) {
    Socket clientSocket = serverSocket.accept();
    threadPool.submit(() -&gt; {
        // Communicate with clientSocket, for example:
        Presse p = new Presse(clientSocket);
        // You&#39;ll want to have this code in a separate method
    });
}

huangapple
  • 本文由 发表于 2020年8月17日 20:16:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63450623.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定