XML Socket and Regular Socket in Flash/Flex does not send message immediately.
- by kramer
I am trying to build a basic RIA where my Flex application client opens an XML socket, sends the xml message "people_list" to server, and prints out the response. I have ruby at the server side and I have successfully set up the security policy stuff.
The ruby xml server, successfully accepts the connections from Flex, successfully detects when they are closed and can also send messages to client. But; there is a problem... It cannot receive messages from flex client. The messages sent from flex client are queued and sent as one package when the socket is closed. Therefore, the whole wait-for-request-then-reply thing is not working...
This is also -kinda- mentioned in the XMLSocket.send() document, where it is stated that the messages are sent async so; they may be delivered at any time in future. But; I need them to be synced, flushed or whatever.
This is the server side code:
require 'socket'
require 'observer'
class Network_Reader_Ops
include Observable
@@reader_listener_socket = UDPSocket.new
@@reader_broadcast_socket = UDPSocket.new
@@thread_id
def initialize
@@reader_broadcast_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, 1)
@@reader_broadcast_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
@@reader_listener_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
@@reader_broadcast_socket.bind('', 50050)
@@reader_listener_socket.bind('', 50051)
@@thread_id = Thread.start do
loop do
begin
text, sender = @@reader_listener_socket.recvfrom_nonblock 1024
print("Knock response recived: ", text)
notify_observers text
rescue Errno::EAGAIN
retry
rescue Errno::EWOULDBLOCK
retry
end
end
end
end
def query
@@reader_broadcast_socket.send("KNOCK KNOCK", 0, "255.255.255.255", 50050)
end
def stop
Thread.kill @@thread_id
end
end
class XMLSocket_Connection
attr_accessor :connection_id
def update (data)
connection_id.write(data+"\0")
end
end
begin
# Set EOL for Flash
$/ = '\x00'
xml_socket = TCPServer.open('', '4444')
security_policy_socket = TCPServer.open('', '843')
xml_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
security_policy_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
a = Thread.start do
network_ops = nil
loop {
accepted_connection = xml_socket.accept
print(accepted_connection.peeraddr, " is accepted\n")
while accepted_connection.gets
incoming = $_.dump
print("Received: ", incoming)
if incoming == "<request>readers on network</request>" then
network_ops = Network_Reader_Ops.new
this_con = XMLSocket_Connection.new
this_con.connection_id = accepted_connection
network_ops.add_observer this_con
network_ops.query
end
end
if not network_ops.nil? then
network_ops.delete_observer this_con
network_ops.stop
network_ops = nil
end
print(accepted_connection, " is gone\n")
accepted_connection.close
}
end
b = Thread.start do
loop {
accepted_connection = security_policy_socket.accept
Thread.start do
current_connection = accepted_connection
while current_connection.gets
if $_ =~ /.*policy\-file.*/i then
current_connection.write("<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>\0")
end
end
current_connection.close
end
}
end
a.join
b.join
rescue
puts "FAILED"
retry
end
And this is the flex/flash client side code:
UPDATE: I have also tried using regular socket and calling flush() method but; the result was same.
private var socket:XMLSocket = new XMLSocket();
protected function stopXMLSocket():void
{
socket.close();
}
protected function startXMLSocket():void
{
socket.addEventListener(DataEvent.DATA, dataHandler);
socket.connect(xmlSocketServer_address, xmlSocketServer_port);
socket.send("<request>readers on network</request>");
}
protected function dataHandler(event:DataEvent):void
{
mx.controls.Alert.show(event.data);
}
How do I achieve the described behaviour?