简体   繁体   English

Java / Android-通过套接字同时发送和接收数据的正确方法

[英]Java/Android - Proper way to send and receive data at the same time through a socket

I'm currently working on an android project that is a sort of P2P application (no central server, IP addresses are entered manually). 我目前正在研究一种P2P应用程序的android项目(没有中央服务器,手动输入IP地址)。 I've already sorted out how two devices are able to connect to each other, but what I seem to be having trouble figuring out is the best way to send data back and forth with a socket. 我已经弄清了两个设备如何相互连接,但是我似乎很难弄清楚是使用套接字来回发送数据的最佳方法。

Right now, I've got two separate threads, one for sending data, and one for receiving data so that neither attempt blocks the other. 现在,我有两个单独的线程,一个用于发送数据,一个用于接收数据,因此任何尝试都不会阻止另一个线程。 My receiving thread checks the output stream, looking for an int until one exists. 我的接收线程检查输出流,寻找一个int直到存在。 The int is a flag for the type of data being sent, and depending on that flag, the application prepares to grab the rest of the data, it's all predictable. int是要发送的数据类型的标志,根据该标志,应用程序准备捕获其余数据,所有这些都是可预测的。

My problem comes in when trying to set up the sending thread. 我的问题出现在尝试设置发送线程时。 I was originally going to have it so that a call on the Sender object (an extension of Thread) would simply send the all the data needed, but realized that doing that didn't actually function within the thread. 我本来打算使用它,以便对Sender对象(Thread的扩展)的调用将仅发送所需的所有数据,但我意识到这样做实际上并没有在线程内起作用。

Instead, I changed it so that the thread constantly runs and checks for a flag that determines the data going to be sent. 相反,我对其进行了更改,以使线程不断运行并检查用于确定将要发送的数据的标志。 A function is called from the UI thread, which prepares the data as class members, and then sets the flag, where it is then "picked up" by the thread and sent off to the other device. 从UI线程调用一个函数,该函数将数据准备为类成员,然后设置标志,然后在该标志中由线程“拾取”并发送给其他设备。 However, I realized this would take up a really unnecessary amount of processor time since the loop would be checking the flag over and over. 但是,我意识到这将占用非常不必要的处理器时间,因为循环将反复检查该标志。

I'm just wondering what the proper way to do this is since android doesn't allow network operations on the UI thread. 我只是想知道什么是正确的方法,因为android不允许在UI线程上进行网络操作。 Would I have to rewrite the Sender object to create a new thread every time it sends a message? 每次发送消息时,我都必须重写Sender对象以创建一个新线程吗?

The Sender thread can be halted via wait() . 可以通过wait()暂停发送方线程。 The Thread can be later resumed by sending it a notify() . 稍后可以通过向它发送notify()来恢复该线程。 An short example for the sender would be: 发送者的简短示例是:

synchronized(this){
  wait();
}


synchronized(sender){
  sender.notify();
}

Edit: Obviously, in the above case "this" and "sender" refer to the same Object (the Sender Thread). 编辑:显然,在上述情况下,“ this”和“ sender”指的是同一对象(“发送方线程”)。

Edit2: Clarification where you need to add those statements. Edit2:澄清您需要在其中添加这些语句的地方。 Given your description i assume you have something similiar to the following 根据您的描述,我认为您有以下类似之处

public void run(){
  while(alive){
    // synchronized(this){
    if  (getFlags()!=null){
      //send data
      setFlags(null);
    }
    // wait();}
  }
}

in your Sender class. 在您的Sender类中。 With the synchronized and wait you can keep the Thread from consuming all available cpu resources from a core. 使用synced and wait,可以防止线程消耗内核中所有可用的cpu资源。 Additionally you will need to modify the calling Thread. 另外,您将需要修改调用线程。 You will have add the following: 您将添加以下内容:

public void handleEvents(..) {
  // process the event
  // determine what to send
  // synchronized(sender) {
  sender.setFlags(mydata);
  // sender.notify();}
}

Note: If you modify data here that gets accessed in the sender thread you will need to move the synchronized statement further up as this will block the current thread. 注意:如果您在此处修改在发送方线程中访问的数据,则将需要进一步向上移动同步语句,因为这将阻塞当前线程。 If the sender blocks too long you might consider queuing the data (eg by having Lists of Objects instead of just Objects) and checking a boolean flag before entering the synchronized block. 如果发送方阻塞的时间太长,您可以考虑对数据进行排队(例如,通过拥有对象列表而不只是对象),并在进入同步块之前检查布尔值标志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM