I´m having problems with receiving long data (>1024bytes) in a simple twisted server implementation.
From the beginning, I´m developing an ios App that has to synchronize with a twisted server. I prepare the information to send in JSON format. Then I start to send that data in chuncks (right now in chunck of 256bytes + 4 bytes for the command - Yes, I´m implementing my own protocol). The connection is ok, and I receive those packet´s in my server (in the dataReceived function of my own Protocol subclass).
The ios method: NSInteger writtenBytes =[self.outputStream write:[data bytes] maxLength:[data length]] return the written bytes into the stream. For the first 4 packets the value returned is the expected (260 bytes). If I have more available bytes to send, the next time I call that method it returns 0 (which apple documentation says: "If the receiver is a fixed-length stream and has reached its capacity, 0 is returned.").
So I deduce that the input buffer is full. I don´t know how to free that buffer (I don´t know how to reach that buffer). I don't know where is the limit of that buffer (it seems to me almost ridiculous).
This is a basic test of the server (Just the important things for this question with a basic based in strings protocol)
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
class IphoneSync(Protocol):
def __init__(self):
self.__buffer = ""
def connectionMade(self):
self.transport.write("0:")
self.factory.clients.append(self)
print "clients are ", self.factory.clients
def connectionLost(self, reason):
self.factory.clients.remove(self)
def dataReceived(self, data):
#print "data is ", data
a = data.split(':')
if len(a) > 1:
command = a[0]
content = a[1]
msg = ""
if command == "iam":
#user&Pass checking
msg = "1"
elif command == "msg":
self.__buffer += data
msg = "1: continue"
elif command == "fin":
#procesaremos todo
#Convertir datos en json
#insertar/actualizar data en sqlite
#devolver respuesta
print "buffer is", self.__buffer
msg = "2: procesing"
print msg
self.transport.write(msg)
#for c in self.factory.clients:
#c.message(msg)
def message(self, message):
self.transport.write(message)
#self.transport.write(message + '\n')
factory = Factory()
factory.protocol = IphoneSync
factory.clients = []
dir(factory)
reactor.listenTCP(8000, factory)
print "Iphone Chat server started"
reactor.run()
I saw the LineReceiver class but i´m not sending lines. The transfered data could be very big (10Mb-50Mb). I´m thinking about the Consumer/Producer model, or RPC Protocols like (AMP, or PB) as a solution but i wanted to work with my own protocol.
If someone knows how to help me, i´ll appreciate very much. Thanks anyway.
The connection is ok, and I receive those packet´s in my server (in the dataReceived function of my own Protocol subclass).
Probably not. TCP is a "stream oriented" protocol. Your application's use of it is not in terms of packets but in terms of a sequence of bytes. There is no guarantee whatsoever that dataReceived will be called with the same string that you passed to outputStream write. If you write "hello, world", dataReceived may be called with "hello, world" - or it may be called twice, first with "hello," and then with " world". Or it may be called 12 times: first "h", then "e", then "l", etc.
And if you call outputStream write twice, once with "hello," and once with " world", then it's entirely possible dataReceived will be called just once with "hello, world". Or perhaps twice, but with "h" and then "ello, world".
So this brand new protocol you're inventing (which I see you mentioned you recognized you were doing, but you didn't explain why this is a good idea or an important part of your application, instead of just a large source of potential bugs and a poor use of time :) has to do something called "framing" in order to let you actually interpret the byte sequence being passed around. This is why there are protocols like AMP.
To actually answer your question, outputStream write returns the number of bytes it was actually able to buffer for sending. You must always check its return value and re-try writing any bytes it wasn't able to send, preferably after waiting for notification that there is more buffer space. Buffer space becomes available after bytes using that space are sent across the network and acknowledged by the receiver. This takes time, as networks are not instantaneous. Notification about buffer space being available comes in many forms, the oldest and most widespread of which (but not necessarily the best in your environment), the select(2) system call.
In addition to Jean-Paul Calderone's answer (ensuring that data are being sent completely from the obj-c side by using select or thread), for protocol part I would suggest using length-prefixed string (AKA Netstring) for simple use case.
Here's an implementation. Whenever something is received, you need to call NSBuffer.write then NSBuffer.extract to get available strings.
Related
In Python I have the option of using a "poller" object which polls blocking sockets for messages waiting and unblocks after a specified number of milliseconds (in the case below, 1000, in the while True block):
import zmq
# now open up all the sockets
context = zmq.Context()
outsub = context.socket(zmq.SUB)
outsub.bind("tcp://" + myip + ":" + str(args.outsubport))
outsub.setsockopt(zmq.SUBSCRIBE, b"")
inreq = context.socket(zmq.ROUTER)
inreq.bind("tcp://" + myip + ":" + str(args.inreqport))
outref = context.socket(zmq.ROUTER)
outref.bind("tcp://" + myip + ":" + str(args.outrefport))
req = context.socket(zmq.ROUTER)
req.bind("tcp://" + myip + ":" + str(args.reqport))
repub = context.socket(zmq.PUB)
repub.bind("tcp://" + myip + ":" + str(args.repubport))
# sort out the poller
poller = zmq.Poller()
poller.register(inreq, zmq.POLLIN)
poller.register(outsub, zmq.POLLIN)
poller.register(outref, zmq.POLLIN)
poller.register(req, zmq.POLLIN)
# UDP socket setup for broadcasting this server's address
cs = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
cs.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# housekeeping variables
pulsecheck = datetime.utcnow() + timedelta(seconds = 1)
alivelist = dict()
pulsetimeout = 5
while True:
polls = dict(poller.poll(1000))
if inreq in polls:
msg = inreq.recv_multipart()
if msg[1] == b"pulse": # handle pluse
ansi("cyan", False, textout = " pulse" + "-" + msg[0].decode())
if not msg[0] in alivelist.keys():
handlechange(msg[0])
alivelist[msg[0]] = datetime.utcnow() + timedelta(seconds = pulsetimeout)
if outsub in polls:
msgin = outsub.recv_multipart()[0]
repub.send(msgin) # republish
msg = unpacker(msgin)
if isinstance(msg, dict):
valu = msg.get("value")
print(".", end = "", flush = True)
else:
ansi("green", False, textout = msg)
if req in polls:
msg = req.recv_multipart()
valmsg = validate_request(msg)
if not valmsg[0]:
ansi("red", True); print(valmsg[1]); ansi()
elif len(alivelist) > 0:
targetnode = random.choice(list(alivelist.keys()))
inreq.send_multipart([targetnode, packer(valmsg[1])])
ansi("blue", True, textout = "sent to " + targetnode.decode())
else:
ansi("red", True, textout = "NO CONNECTED NODES TO SEND REQUEST TO")
if outref in polls:
msg = outref.recv_multipart()
destinataire, correlid = msg[1].split(b"/")
req.send_multipart([destinataire, correlid, msg[2]])
I want to implement something analogous in Elixir (or Erlang) but my preferred native library, chumak, doesn't seem to implement polling. How do I implement non-blocking receives in Erlang/Elixir, preferably using Chumak, but I'll move to another Erlang zeroMQ library if necessary? My socket pattern preference is router sends, dealer receives.
EDIT
My use case is the following. I have a third party financial service which serves data based on requests, with answers coming asynchronously. So you can send multiple requests, and you'll get responses back after an unspecified period of time, and not necessarily in the same order you sent them.
So I need to connect this service into Erlang (actually Elixir) and ZeroMQ seems like a good fit. Multiple users connected (via Phoenix) to Erlang/Elixir will send requests, and I need to pass these on to this service.
The problem comes if there is an error in one of the requests, or the third party service has some kind of problem. I will be blocking-waiting for a response, and then unable to service new requests from Phoenix.
Basically I want to listen constantly for new requests, send them over, but if one request doesn't produce a response, I will have one-fewer responses than requests and that will lead to an eternal wait.
I understand that if I send requests separately, then the good ones will produce responses so I don't need to worry about blocking even if, over time, I get quite a big numerical difference between requests sent and responses received. Maybe the design idea is that I shouldn't worry about this? Or should I try to track one-for-one responses to requests and timeout the non-responses somehow? Is this a valid design pattern?
Is your system constantly connected to the asynchronous query resource, or are you making a new connection with each query?
Each situation has its own natural model in Erlang.
The case of: A single (or pool of) long-term connection(s)
Long-term connections that maintain a session with the resource (the way a connection with a database would work) are most naturally modelled as processes within your system that have the sole job of representing that external resource.
The requirements of that process are:
Translate the external resource's messages into internally meaningful messages (not just passing junk through -- don't let raw, external data invade your system unless it is totally opaque to you)
Keep track of timed out requests (and this may require something sort of like polling, but can be done more precisely with erlang:send_after/3
This implies, of course, that the module that implements this process will need to speak the protocol of that resource. But if this is accomplished then there really isn't any need for a messaging broker like an MQ application.
This allows you to have that process be reactive and block on receive while the rest of your program goes off to do whatever its doing to do. Without some arbitrary polling that will surely run you into the Evil Black Swamp of Scheduling Issues.
The case of: A new connection per query
If each query to the resource requires a new connection the model is similar, but in here you spawn a new process per query and it represents the query itself within your system. It blocks waiting for the response (on a timeout), and nothing else matters to it.
That is the easier model, actually, because then you don't have to scrub a list of past, possibly timed out requests that will never return, don't have to interact with a set of staged timeout messages sent via erlang:send_after/3, and you move your abstraction one step closer to the actual model of your problem.
You don't know when these queries will return, and that causes some potential confusion -- so modeling each actual query as a living thing is an optimal way to cut through the logical clutter.
Either way, model the problem naturally: As a concurrent, asynch system
In no case, however, do you want to actually do polling the way you would in Python or C or whatever. This is a concurrent problem, so modelling it as such will provide you a lot more logical freedom and is more likely to result in a correct solution that lacks corners that give rise to weird cases.
I have an application that sends JSON objects over AMQP, and I want to inspect the network traffic with Wireshark. The AMQP dissector gives the payload as a series of bytes in the field amqp.payload, but I'd like to extract and filter on specific fields in the JSON object, so I'm trying to write a plugin in Lua for that.
Wireshark already has a dissector for JSON, so I was hoping to piggy-back on that, and not have to deal with JSON parsing myself.
Here is my code:
local amqp_json_p = Proto("amqp_json", "AMQP JSON payload")
local amqp_json_result = ProtoField.string("amqp_json.result", "Result")
amqp_json_p.fields = { amqp_json_result }
register_postdissector(amqp_json_p)
local amqp_payload_f = Field.new("amqp.payload")
local json_dissector = Dissector.get("json")
local json_member_f = Field.new("json.member")
local json_string_f = Field.new("json.value.string")
function amqp_json_p.dissector(tvb, pinfo, tree)
local amqp_payload = amqp_payload_f()
if amqp_payload then
local payload_tvbrange = amqp_payload.range
if payload_tvbrange:range(0,1):string() == "{" then
json_dissector(payload_tvbrange:tvb(), pinfo, tree)
-- So far so good. Let's look at what the JSON dissector came up with.
local members = { json_member_f() }
local strings = { json_string_f() }
local subtree = tree:add(amqp_json_p)
for k, member in pairs(members) do
if member.display == 'result' then
for _, s in ipairs(strings) do
-- Find the string value inside this member
if not (s < member) and (s <= member) then
subtree:add(amqp_json_result, s.range)
break
end
end
end
end
end
end
end
(To start with, I'm just looking at the result field, and the payload I'm testing with is {"result":"ok"}.)
It gets me halfway there. The following shows up in the packet dissection, whereas without my plugin I only get the AMQP section:
Advanced Message Queueing Protocol
Type: Content body (3)
Channel: 1
Length: 15
Payload: 7b22726573756c74223a226f6b227d
JavaScript Object Notation
Object
Member Key: result
String value: ok
Key: result
AMQP JSON payload
Result: "ok"
Now I want to be able to use these new fields as display filters, and also to add them as columns in Wireshark. The following work for both:
json (shows up as Yes when added as a column)
json.value.string (I can also filter with json.value.string == "ok")
amqp_json
But amqp_json.result doesn't work: if I use it as a display filter, Wireshark doesn't show any packets, and if I use it as a column, the column is empty.
Why does it behave differently for json.value.string and amqp_json.result? And how can I achieve what I want? (It seems like I do need a custom dissector, as with json.value.string I can only filter on any member having a certain value, not necessarily result.)
I found a thread on the wireshark-dev mailing list ("Lua post-dissector not getting field values", 2009-09-17, 2009-09-22, 2009-09-23), that points to the interesting_hfids hash table, but it seems like the code has changed a lot since then.
If you'd like to try this, here is my PCAP file, base64-encoded, containing a single packet:
1MOyoQIABAAAAAAAAAAAAAAABAAAAAAAjBi1WfYOCgBjAAAAYwAAAB4AAABgBMEqADcGQA
AAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAB/tcWKO232y46mkSqgBgxtgA/AAAB
AQgKRjDNvkYwzb4DAAEAAAAPeyJyZXN1bHQiOiJvayJ9zg==
Decode with base64 -d (on Linux) or base64 -D (on OSX).
It turns out I shouldn't have tried to compare the display property of the json.member field. Sometimes it gets set by the JSON dissector, and sometimes it just stays as Member.
The proper solution would involve checking the value of the json.key field, but since the key I'm looking for presumably would never get escaped, I can get away with looking for the string literal in the range property of the member field.
So instead of:
if member.display == 'result' then
I have:
if member.range:range(1, 6):string() == 'result' then
and now both filtering and columns work.
Ruby novice. First time post so excuse any communication protocol inadequacies :)
This site has been a great help and a "HUGE!!!" shoutout of thanks to all.
I need to connect my rails app to an electricity providers api so I can vend electricity to my web customers. I'm needing some help to simply get an initial request sent to the API
IP: 41.204.194.188
Port: 8945
First block: What is a message variable length indicator (VLI)?
"2 bytes precede every message sent to/from BizSwitch. The 2 bytes are referred to as a variable length indicator. Bytes 1-2 indicate the number of bytes in the message (excluding the first 2 bytes). The 2 bytes represent a 16bit unsigned integer in network byte order. Note that if a compressed message is being sent, the message will have to first be compressed, in order to determine its length, before being sent."
Ignore compression.
link to api doc: https://dl.dropboxusercontent.com/u/3815995/Ipay-prepaidElecTransactionSpec.pdf
Simple Vend Request example:
<ipayMsg client="ipay" term="1" seqNum="0" time="2002-05-16 10:55:30 +0200">
<elecMsg ver="2.37">
<vendReq>
<ref>136105500001</ref>
<amt cur="ZAR">11400</amt>
<numTokens>1</numTokens>
<meter>A12C3456789</meter>
<payType>cash</payType>
</vendReq >
</elecMsg>
</ipayMsg>
Simple Vend Response example
<ipayMsg client="ipay" term="1" seqNum="0" time="2002-05-16 10:55:35 +0200">
<elecMsg ver="2.37"
<vendRes> <ref>136105500001</ref>
<res code="elec000">OK</res>
<util addr="Megawatt Park, Contact Centre tel 086-003-7566" taxRef="4740101508" distId="6004708001509">Eskom Online</util>
<stdToken units="346.34" rctNum="12345678" amt="10000" tax="1400">12345678901234567890</stdToken>
<rtlrMsg>060000 Warning: This meter is not configured for FBE.</rtlrMsg>
<customerMsg>Meter not registered for Free Basic Electricity. Please apply at your local office.</customerMsg>
</vendRes>
</elecMsg>
</ipayMsg>
I've got this far and I seem connected but how do I actually send and receive responses? I've tried googling for help but yet to find how to send the XML packet and then receive the response.
#!/usr/bin/env ruby
require 'socket'
begin
socket = TCPSocket.new('41.204.194.188', 8945)
rescue => e
puts "error: #{e}"
else
puts "connected"
end
socket.close
Would appreciate any assistance or a nudge in the right direction.
Kind regards,
Jamie
Great I figured it out. Main issue regarding communication to the socket was sending a message variable length indicator. This stackoverflow question put me on the write path "Ruby - How to represent message length as 2 binary bytes"
Step 1: determine the length of my xml message length = message.size
The first field in the header must be the message length which is defined as a 2 binary byte message length in network byte order.
Step 2: message_variable_length_indicator = [length].pack("n")
Step 3: Connect to socket streamSock = TCPSocket::new('41.204.194.188', 8945)
Step 4: streamSock.write(message_variable_length_indicator)
Step 5: streamSock.write(message)
Step 6: get a response str = streamSock.recvfrom(1000)
Now to deal with timeout but at least I'm connecting :)
I have done this in PHP may be you will get idea from below code its working fine for my request.
function sendSocketRequest($XmlString, $Socket_Request) {
if (!($sock = socket_create(AF_INET, SOCK_STREAM, 0))) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
if (!socket_connect($sock, $Socket_Request['HostName'], $Socket_Request['Port'])) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not connect: [$errorcode] $errormsg \n");
}
$status = socket_write($sock, pack_int32be(strlen($XmlString)), 4);
$status = socket_write($sock, $XmlString, strlen($XmlString));
$response = socket_read($sock, $this->_socketReadLength);
socket_close($sock);
return substr($response, 2);
}
function pack_int32be($i) {
if ($i < -2147483648 || $i > 2147483647) {
die("Out of bounds");
}
return pack('C4', ($i >> 24) & 0xFF, ($i >> 16) & 0xFF, ($i >> 8) & 0xFF, ($i >> 0) & 0xFF
);
}
$socketResponse = sendSocketRequest($yourXMLString, array('HostName'=>'<HostName>','Port'=>'<Port>');
I need some help using socket "select" function.
My server code is like this:
while true do
for _,server in pairs(servers) do
local client = server:accept()
client:settimeout(5)
local line, err = client:receive()
if not err then
client:send(line .. "_SERVER_SIDE\n")
else
client:Send("___ERRORPC"..err)
end
client:close()
end
end
But now i want to use the select function instead of make a forever loop like this.
Reading this: http://w3.impa.br/~diego/software/luasocket/socket.html
I know that i can use something simmilar than:
socket.select(servers, nil, 5)
But i don´t know how i can use this on the code above. Can anyone help me?
I will have to use this inside a while true statement?
The reading operation (first parameter) means that i can only make an accept/receive]? And the seconds parameter means that i can only make a send?
As per the documentation, select receives one or two arrays of sockets and returns an array of sockets that can safely be read from without blocking and an array of sockets that can be safely written to without blocking and an array of sockets that can safely be written without blocking. An important point is that the first array is for both server sockets that want you want to call accept on and for client sockets that you want to call receive on.
The seconds parameter is just a timeout for the select. It doesn't have to do with how many operations you can make.
The basic thing you are going to have to change in your code is that when a receive call fails with a timeout, instead or giving an error you should add that socket to the array of sockets that you pass to select. This way you can have select tell you when that socket becomes active again.
From the documentation for select: "calling select with a server socket in the receive parameter before a call to accept does not guarantee accept will return immediately. Use the settimeout method or accept might block forever." This means that you'd need to use settimeout before your accept call, but assuming you have a list of opened connections you can work with in servers table, you can use select in the following way:
local canread = socket.select(servers, nil, 1)
for _,client in ipairs(canread) do
local line, err = client:receive()
if not err then
client:send(line .. "_SERVER_SIDE\n")
else
client:send("___ERRORPC"..err)
end
end
socket.select will block for up to 1 second, but will return sooner if there is a socket from the list you provided that can be read from. You can block indefinitely if you use socket.select(servers, nil, 0); blocking for some short time is useful if you need to do some other work while waiting for the input.
Updated to use ipairs instead of pairs as the returns table is keyed both on numbers as well as on sockets themselves, so if one socket can be read from, the returned array looks like {[1] = sock, [sock] = 1}.
single demo
local server = socket.bind("*",7777)
local client_tab = {}
while true do
-- socket.select first param is a table of connected socket,
-- you want a connected socket,you need to call accept()
-- if you do not want to block,you should call settimeout(seconds)
local recvt = socket.select(client_tab, nil, 1)
server:settimeout(1)
local client = server:accept()
if client then
client_tab[#client_tab+1] = client
end
if #recvt > 0 then
-- read clients in recvt
end
end
another Vala problem occured: I try to send and receive data via UDP. The sending works and via Wireshark I can see that the server sends the expected result. Problem is: My program doesn't get the data.
I checked and I can see that, when a socket has been created to send the UDP data, the specific port stays open, which is confirmed by Wireshark because my PC doesn't send any of those ICMP messages back to the server.
What I got so far:
try
{
SocketClient mySocket = new SocketClient();
mySocket.protocol = SocketProtocol.UDP;
mySocket.type = SocketType.DATAGRAM;
var conn = mySocket.connect (new InetSocketAddress(addr,targetPort));
conn.output_stream.write(themessage_in_a_uint8_array);
DataInputStream response = new DataInputStream (conn.input_stream);
string resp ="";
char myChar;
try
{
do
{
myChar = (char)response.read_byte();
print ("Response" + myChar.to_string());
}while(true);
}
catch(Error e)
{
print(e.message);
}
}
catch(Error e)
{print(e.message);}
What currently happens: The message is send, the string 'Response' is printed once into the console and after that it just loops.
If I check response.get_available() it returns 0.
I can check with lsof | grep used_portnumber and sure enough, the used socket stays open. What am I doing wrong?
I am not sure but this is what I suspect:
UDP is a datagram protocol (data is explicitly chopped into data). Server have sent one datagram to client. Now in BSD Sockets (and after it everywhere) if the underlaying socket have datagram type then read reads the full packet. If the buffer have insufficient length the message is truncated.
The solution is read in one byte. For example
uint8[] buffer = new uint8[1 << 16]; // Maximum UDP length - we don't loose anything
unowned string locale;
bool need_convert = GLib.get_charset (out locale);
do {
ssize_t len = response.read (buffer);
string text;
if (need_convert) {
text = GLib.convert ((string)buffer, len, locale, "UTF-8");
} else {
text = (string)buffer;
}
stdout.print("Response " + text);
} while (true);
Edit I have change the code to print UTF-8 text - without assuming current locale is "UTF-8"-based.
PS 1 This is my guess as it is one gotcha of BSD Sockets (also Winsockets and everything that builds on this) that come to my mind. Please be graceful if the question will be more specific (i.e. it is not the answer to question).
PS 2 In general I would recommend against mixing bytes and chars. While in ASCII-compatible encodings (ISO, UTF-8) sending ASCII subset of chars is safe it will bite when attempt on CJK encodings or if sender will send 'ą' by UTF-8 and sender will treat it as ISO-8859-2 (where this character have different encoding). I assume it is for the toy-examples only. If not you may want to read What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text.