java - 如何使用OscP5监听tcp变化?

标签 java tcp processing osc

我正在使用OscP5在 TCP 模式下,但我似乎无法弄清楚 如何监听 TcpClient 连接或断开等变化。

我像这样实例化 oscP5:

tcp = new OscP5(this, TCP_PORT, OscP5.TCP);

但是,例如,与 TcpServer 监听器相关的任何内容都会导致空引用错误

println(tcp.tcpServer().getListeners());

我同时想到的一个巧妙的解决方法是不断计算连接数:

tcp.tcpServer().size()

如果数量增加,则客户端已连接,如果数量减少,则客户端已断开连接。问题是,当客户端断开连接时,我无法想出一种方法来知道断开连接的 ip/客户端 id,除非我有自己的列表并检查我自己的客户端列表中缺少哪个客户端。这感觉非常hacky并且可能容易出错:

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.swing.JOptionPane;

import netP5.NetListener;
import netP5.NetMessage;
import netP5.NetStatus;
import netP5.TcpClient;
import oscP5.OscEventListener;
import oscP5.OscMessage;
import oscP5.OscP5;
import oscP5.OscStatus;
import processing.core.PApplet;


public class TCPServer extends PApplet implements NetListener,OscEventListener {

    public static final int TCP_PORT = 32002;

    private OscP5 tcp;
    private int maxClients = 100;
    private TcpClient[] clients = new TcpClient[maxClients];
    private HashMap<String,Integer> clientsMap = new HashMap<String, Integer>();//lookup table to check against duplicates
    private int prevSize = 0;//previous tcp server client list size

    public void setup() {
        size(1000,100);
        tcp = new OscP5(this, TCP_PORT, OscP5.TCP);
        tcp.addListener(this);
    }

    public void draw() {
        int currSize = tcp.tcpServer().size();//get updated size of clients list
        //if there was a change, a client either connected or disconnected
        if(currSize > prevSize) connect(tcp.tcpServer().getClient(prevSize));//prevSize = size-1 at this point
        if(currSize < prevSize) disconnect(); 
        prevSize = currSize;//update internal client size list

        background(255);
        for (int i = 0; i < maxClients; i++) {
            fill(clients[i] == null ? 255 : 127);
            rect(i*10,0,10,10);
        }
    }

    public void oscEvent(OscMessage m) {
        println(m);
    }

    private void connect(TcpClient client){
        String ip = client.netAddress().address();
        if(clientsMap.get(ip) == null){//if the ip is not a duplicate
            int id = getNextAvailableSlot();
            clients[id] = client;//keep track of this client
            clientsMap.put(ip, id);//and it's ip in the LUT
            println("connected " + ip + " at index " + id);
        }
    }
    private void disconnect(){
        List<TcpClient> c = Arrays.asList(tcp.tcpServer().getClients());//not very efficient, just lazy piggyback ride for contains
        for(int i = 0; i < maxClients; i++){//go through locally stored clients
            if(clients[i] != null){//if we one
                if(!c.contains(clients[i])) {//check if it's not already on the updated tcp server client list
                    String ip = clients[i].netAddress().address();
                    clientsMap.remove(ip);//clear LUT entry
                    tcp.tcpServer().remove(clients[i]);//disconnect
                    clients[i].dispose();//close
                    clients[i] = null;//request cleanup
                    println("disconnected " + ip);
                    return;
                }
            }
        }
    }
    private int getNextAvailableSlot(){
        for (int i = 0; i < maxClients; i++)
            if(clients[i] == null) return i;
        return -1;
    }

    public static void main(String[] args) {
        PApplet.main(TCPServer.class.getSimpleName());
    }

    @Override
    public void netEvent(NetMessage e) {
        System.out.println("netEvent:");
        System.out.println(e);
    }

    @Override
    public void netStatus(NetStatus s) {
        System.out.println("netStatus:");
        System.out.println(s);
    }

    @Override
    public void oscStatus(OscStatus s) {
        System.out.println("oscStatus:");
        System.out.println(s);
    }

}

在这种情况下监视 tcp 客户端连接/断开事件的干净方法是什么?

最佳答案

目前 oscP5 中还没有实现这样的概念。这是类似的discussion .

似乎你必须根据调试信息中找到的内存地址自己构建一些东西,例如### 新客户端@ netP5.TcpClient@164b9b6。我扫描 System.out 流中的字符串 new Client,然后调用方法 clientConnected。 这完全是 hacky,但我目前没有看到其他方法。

import java.io.PrintStream;

import oscP5.*;
import netP5.*;

OscP5 oscP5tcpServer;
OscP5 oscP5tcpClient;
NetAddress myServerAddress;

void setup() {
  // overwrite standard System.out
  System.setOut(new PrintStream(System.out) {
    public void println(String s) {
      if(s.indexOf("new Client") != -1){
        clientConnected(getMemoryAddress(s));
      }
      super.println(s);
    }
    // override some other methods?
  });

  oscP5tcpServer = new OscP5(this, 11000, OscP5.TCP);
  oscP5tcpClient = new OscP5(this, "127.0.0.1", 11000, OscP5.TCP);
}

void clientConnected(int memoryAddress){
  println("Client connected, with memory address " + memoryAddress);
}

int getMemoryAddress(String s){
  return Integer.parseInt(s.substring(s.lastIndexOf('@')+1), 16);
}

void draw() {  
}

void mousePressed() {
  oscP5tcpClient.send("/test", new Object[] {new Integer(1)});
}

void keyPressed() {
  println(oscP5tcpServer.tcpServer().getClients().length);
}

void oscEvent(OscMessage theMessage) {
  System.out.println("### got a message " + theMessage);
  if(theMessage.checkAddrPattern("/test")) {
    OscMessage m = new OscMessage("/response");
    m.add("server response: got it");
    oscP5tcpServer.send(m,theMessage.tcpConnection());
  }
}

关于java - 如何使用OscP5监听tcp变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17505058/

相关文章:

java - 服务器返回 HTTP 响应代码 : 401 for URL: https

java - 如何提取Java中写入文件的数据结尾

java - oracle 上的 select SQL 语句是否锁定已使用的表以供其他连接更新?

java.net.ConnectException : Connection refused

android - 尝试为 Android 应用程序导出签名包时出现错误 "setTestClassesDir(File) method has been deprecated"

java - 计算贝塞尔剪裁中的距离函数时遇到问题

Java实现检查两条线段之间的交点?

c# - 通过 TCP 发送文本字符串?

java - Tomcat 6.0 应用程序中的内存泄漏

java - 为什么我的 PVector 应该保持不变,但在此草图中被修改