How to flush a socket in my code

孤者浪人 提交于 2020-01-26 02:30:20

问题


I'm writing through a socket from a FF add-on to a java server. I write several requests and the server seems to process them one-by-one. In contrast, the responses from the server are processed all at the same time.

I've tried flushing the out stream in the server but it does nothing. I don't understand what's going on.

I appreciate any help, thank you.

EDIT1: May be the add-on (client) is not flushing the input stream, is that possible? I'm using in the java server the out.println so the '\n' must flusht its output stream and the net library uses the write.flush(), but I don't see any other flush for the input.

EDIT2: Here is my code:

exports.main = function() {
    try  {
        // At first, we need a nsISocketTransportService
        var transportService =  
            Cc["@mozilla.org/network/socket-transport-service;1"]
            .getService(Ci.nsISocketTransportService);  

        // Try to connect to localhost:2222
        var transport = transportService.createTransport(null, 0, "localhost", 6666, null);  

        var stream = transport.openInputStream(Ci.nsITransport.OPEN_UNBUFFERED,null,null); 
        var instream = Cc["@mozilla.org/scriptableinputstream;1"]
            .createInstance(Ci.nsIScriptableInputStream); 

        // Initialize
        instream.init(stream);
        var outstream = transport.openOutputStream(0, 0, 0);



        var dataListener = { 
            onStartRequest: function(request, context){},

            onStopRequest: function(request, context, status){
                instream.close();
                outstream.close();
            }, 

            onDataAvailable: function(request, context, inputStream, offset, count) { 
                var data = instream.read(count); 
                console.log(data);             
            }, 
        };

        var pump = Cc["@mozilla.org/network/input-stream-pump;1"]
                .createInstance(Ci.nsIInputStreamPump); 
        pump.init(stream, -1, -1, 0, 0, false); 
        pump.asyncRead(dataListener, null); 

        // Write data
        console.log("hi1");
        var outputData = "hi1\n";
        outstream.write(outputData, outputData.length);

        // Write data
        console.log("hi2");
        var outputData = "hi2\n";
        outstream.write(outputData, outputData.length);

    } catch (e){ 
        console.log("Error" + e.result + ": " + e.message); 
        return e; 
    } return null;
};

So, when I run it, I get:

Client > hi1
Client > hi2
Server > bye1
Server > bye2

And it should be:

Client > hi1
Server > bye1
Client > hi2
Server > bye2

回答1:


You are writing to the output stream synchronously, that means that no other JavaScript code can run while you do it. So receiving anything from the server while you are writing is impossible, incoming data is simply put into a buffer.

The other issue is that you are sending the next string without waiting for the response from server. Normally, you will be able to send off both of them before the server response arrives. You probably want to send the next string only when you receive the response to the previous one.

You probably want to use a send function like this one:

Components.utils.import("resource://gre/modules/NetUtil.jsm");

var toSend = ["hi1\n", "hi2\n"];

function sendNextString(outstream)
{
  if (!toSend.length)
    return;  // Nothing left to send

  var outputData = toSend.shift();
  console.log(outputData);
  var instream = Components.classes["@mozilla.org/io/string-input-stream;1"]
                           .createInstance(Components.interfaces.nsIStringInputStream);
  instream.setData(outputData, outputData.length);

  NetUtil.asyncCopy(instream, outstream);
}

And you would call sendNextString(outstream) in your code after pump.asyncRead() as well as in onDataAvailable.

PS: From what I can tell, flushing the stream is not the issue here - you are using a non-buffering stream.




回答2:


TCP is a stream protocol, so you receive a stream of bytes. If you want packets, you got to implement your own protocol over TCP to be able to separate them. This topic is widely covered on internet.

Edit

This is a common pitfall in socket programming. Most people do not understand at first that a TCP socket is a stream, not a message queue.

I mean, one call to "send" at one end of the socket do not correspond necessarily to one "receive" at the other end. The underlying layers can decide to group or split the bytes sent at will.

So you can have something like this:

  • client sends "ABCD"
  • client sends "EFGH"
  • server receives "AB"
  • server receives "CDEF"
  • server receives "GH"

This is a stream, not a message queue. Think of it as a an infinite file you're reading in.

So, if you want to read strings out of a file, you need some way to separate them. It can be a delimiter, or you can prefix your strings by the string's length, or whatever.



来源:https://stackoverflow.com/questions/10318105/how-to-flush-a-socket-in-my-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!