Reading a varint using cocoaasyncsocket framework - iphone

Has anyone had experience of using cocoaasyncsocket together with google protobuf? I want to seperate frames using a varint, which is simple enough using a client/server combo based on netty, but I don't see a simple way of decoding the initial varint when reading using cocoaasync.

On the C++ side of things, you'll have to use a combination of ReadVarint32() and VarintSize32() do something like this:
char buf[4];
buf = some_api_call(); /* _Copy/peak_ up to 4 bytes off the wire */
CodedInputStream cos(buf, sizeof(buf) - 1);
uint32_t frame_sz;
if (!cos.ReadInputStream(&frame_sz)) {
// Unable to read the frame size
return false;
}
frame_sz should have a valid value that will tell you how many bytes it needs to read.
uint32_t consumed_bytes = CodedOutputStream::VarintSize32(frame_sz);
Now you know how many bytes were consumed to generate frame_sz.
I'd wrap these calls in a library that I extern "C" and would link in from your application.

Related

Simple UDP socket in VC++ MFC

I have been trying to write a working program that takes in data from a UDP socket and displays it in an edit control box as you receive the data (My exposure to c++ is also only about a week :P have only done embedded C code before). I have a working program that can send and output data on a button click but I want something that can do it in real time. The aim is scale this up into a larger GUI program that can send control data to hardware and get responses from them.
I have run into various problems including:
The program just not executing my OnReceivefunction (derived from
CAsyncSocket)
Getting the OnReceive function to run on a separate thread so that it can still run after a button has been clicked sending a control packet to the client then waiting for a response in a while loop
Not being able to output the data in the edit box (tried using both CEdit and CString)
ReplaceSel error saying that the type char is incompatible with LPCTSTR
My code is based on this codeproject.com tutorial, being almost exactly what I want but I get the error in 4.
EDIT: the error in 4. disappears when I change it to a TCHAR but then it outputs random chinese characters. The codeproject.com tutorial outputs the correct characters regardless of char or TCHAR declaration. When debugged my code has type wchar_t instead type char like the other code.
Chinese output
In the working program echoBuffer[0] the character sent and displayed was a 1
UINT ReceiveData(LPVOID pParam)
{
CTesterDlg *dlg = (CTesterDlg*)pParam;
AfxSocketInit(NULL);
CSocket echoServer;
// Create socket for sending/receiving datagrams
if (echoServer.Create(12345, SOCK_DGRAM, NULL) == 0)
{
AfxMessageBox(_T("Create() failed"));
}
for (;;)
{ // Run forever
// Client address
SOCKADDR_IN echoClntAddr;
// Set the size of the in-out parameter
int clntAddrLen = sizeof(echoClntAddr);
// Buffer for echo string
char echoBuffer[ECHOMAX];
// Block until receive message from a client
int recvMsgSize = echoServer.ReceiveFrom(echoBuffer, ECHOMAX, (SOCKADDR*)&echoClntAddr, &clntAddrLen, 0);
if (recvMsgSize < 0)
{
AfxMessageBox(_T("RecvFrom() failed"));
}
echoBuffer[recvMsgSize] = '\0';
dlg->m_edit.ReplaceSel(echoBuffer);
dlg->m_edit.ReplaceSel(_T("\r\n"));
}
}
After reading the link that #IInspectable provided about working with strings and checking the settings differences between the two programs it became clear that the issue lay with an incorrect conversion to UNICODE. My program does not require it so I disabled it.
This has cleared up the issue in 4. and provided solutions for 2 and 3.
I also think I know why another instance of my program would not run OnReceivein 1. because that file was not being defined by one that was already being run by the program, but that is now irrelevant.

Invalid field in source data: 0 TCP_Message

I'm using ProtoBuf-Net for serialize and deserialize TCP_Messages.
I've tried all the suggestions I've found here, so I really don't know where the mistake is.
The serialize is made server side, and the deserialize is made on an application client-side.
Serialize code:
public void MssGetCardPersonalInfo(out RCPersonalInfoRecord ssPersonalInfoObject, out bool ssResult) {
ssPersonalInfoObject = new RCPersonalInfoRecord(null);
TCP_Message msg = new TCP_Message(MessageTypes.GetCardPersonalInfo);
MemoryStream ms = new MemoryStream();
ProtoBuf.Serializer.Serialize(ms, msg);
_tcp_Client.Send(ms.ToArray());
_waitToReadCard.Start();
_stopWaitHandle.WaitOne();
And the deserialize:
private void tpcServer_OnDataReceived(Object sender, byte[] data, TCPServer.StateObject clientState)
{
TCP_Message message = new TCP_Message();
MemoryStream ms = new MemoryStream(data);
try
{
//ms.ToArray();
//ms.GetBuffer();
//ms.Position = 0;
ms.Seek(0, SeekOrigin.Begin);
message = Serializer.Deserialize<TCP_Message>(ms);
} catch (Exception ex)
{
EventLog.WriteEntry(_logSource, "Error deserializing: " + ex.Message, EventLogEntryType.Error, 103);
}
As you can see, I've tried a bunch of different approache, now comented.
I have also tried to deserialize using the DeserializeWithLengthPrefix but it didn't work either.
I'm a bit noob on this, so if you could help me I would really appreciate it.
Thank's
The first thing to look at here is: is the data you receive the data you send. Until you can answer "yes" to that, all other questions are moot. It is very easy to confuse network code and end up reading partial frames, etc. As a crude debugger test:
Debug.WriteLine(Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length));
should work. If the two base-64 strings are not identical, then you aren't working with the same data. This can be because of a range of reasons, including packet splitting and combining. You need to keep in mind that in a stream, what you send is not what you get - at least, not down to the fragment level. You might "send" data in the way of:
one bundle of 20 bytes
one bundle of 10 bytes
but at the receiving end, it would be entirely legitimate to read:
1 byte
22 bytes
7 bytes
All that TCP guarantees is the order and accuracy of the bytes. It says nothing about their breakdown in terms of chunks. When writing network code, there are basically 2 approaches:
have one thread that synchronously reads from a stream and local buffer (doesn't scale well)
async code (very scalable), but accept that you're going to have to do a lot of "do I have a complete frame? if not, append to an input buffer; if so, process any available frame data (could be multiple), then shuffle any incomplete data to the start of the buffer"

sending image as byte array from matlab to java through sockets

I am trying to send images from a matlab server to a java client through a sockets. First I converted the image to a byte array and I used the readFully method on the client side which requires a length to be specified.
The problem is that the size of the byte array changes from one image to the other and when I send the size through the write () method it does not read correctly on the client side.
Here is a snippet of my code
Matlab server
%% convert image
Javaimage=im2java2d (image);
Arraystream=ByteArrayOutputStream;
ImageIO.write (javaimage,'jpg', arraystream)
Arraystream.flush ();
Bytearray=arraystream.toByteArray;
%% send size through output stream
Outstream=write (size (byteArray, 1))
%% send array
outStream=write (byteArray);
On the client side I have tried many methods such as read, readInt, readDouble, but I think the trouble is the write () method I tried to use writeInt () but matlab did not recognize it even though I included the libraries needed:
Java.io
Java.net
Java.io.dataoutputstream
Java.io.datainputstream
I should also include that the size of the array is usually over 10000
I would appreciate any help
Thank you in advance
I have finally found the answer which is so simple that it was the last thing to check.
When I created the socket input and output streams I did the following
InStream =socket.getInputStream;
OutStream=socket.getOutputStream;
This allows you to use the methods from the inputStream class such as read () and write() which are methods that only read bytes.To read any other types of data we must use the dataInputStream and dataOutput stream classes which are a type of filter class that allow reading primitive types such as int , double , etc using methods such as readInt () and writeInt
To do this you need to change the above as follows
Instream=dataInputStream (socket.getInputStream);
OutStream=dataOutputStream (socket.getOutputStream);
And its that simple.

Using GSocketClient, how do I read incoming data without knowing how many incoming bytes there will be?

I am still struggling to be able to read incoming response messages from a piece of hardware my program is communicating with.
I am using a GSocketClient and am able to connect and successfully send messages using g_output_stream_write(). I then want to read the response sent back from the device, but I have no way of knowing how many bytes the reply will be in order to use g_input_stream_read(). I have also tried using g_input_stream_read_all(), but this seems to block the application and never return. I don't know how g_input_stream_read_all() determines that it has reached the end of a stream, but I assume the problem is somewhere there?
I know that there is incoming data because I can use g_input_stream_read() with a made-up byte size like 5 and I then see the first 5 incoming bytes, but the response size will always be different.
So my questions is, is there a way to determine how much data is waiting to be read so that I can plug that into g_input_stream_read() as a variable for the size to read? And if not, what is the correct usage of g_input_stream_read_all() to get it to not block like I am seeing it do?
Does something like the following work?
#define BUF_SIZE 1024
guint8 buffer[BUF_SIZE];
GByteArray *array = g_byte_array_new();
gsize bytes_read;
GError *error = NULL;
while (g_input_stream_read_all(istream, buffer, BUF_SIZE, &bytes_read, NULL, &error))
{
g_byte_array_append(array, buffer, bytes_read);
if (bytes_read < BUF_SIZE)
/* We've reached the end of the stream */
break;
}
if (error)
// error handling code

Printing Receipt on Star Micronics TSP 650 Printer through iPad

I am using Star iOS SDK to print receipts (like a restaurant bill) but am facing problems implementing column settings and cell spacing for proper alignment. I have checked out the documentation but have not found something useful.
The line code manual has some signals/commands which I am unable to understand. Can anyone help me out with that?
The commands referenced in the Line Mode manual need to be converted into bytes and then sent to the printer. The StarIO iOS SDK package you downloaded has a manual called "README_StarIO_POSPrinter_iOS_SDK.pdf". (http://www.starmicronics.com/absolutefm/absolutefm/afmviewfaq.aspx?faqid=175) Did you check out pages 9-15? The StarIO framework is explained here.
Specific to your question about sending commands, page 13 shows you how to write to the port using a byte array, but make sure you add StarIO.framework and open the communication port first.
From the manual:
//Set a byte array to send to the printer
//command = { A, B, C, D, Feed 3mm, Full Cut}
unsigned char command = {0x41, 0x42, 0x43, 0x44, 0x1B, 0x7A, 0x00, 0x1B, 0x64, 0x02};
Uint bytesWritten = 0;
#Try
{
While(bytesWritten < (sizeof command))
{
bytesWritten += [port writePort: command : bytesWritten : sizeof command - bytesWritten];
}
}
#Catch(PortException)
{
//There was an error writing to the port
}
Also described is how to close ports (make sure you close every opened port) and getting printer status.
Let me know if this helps.
I talked to SDK developers of start micronics, as I was facing the same problem using TSP100 model. Here is the reply from one of their tech guy.
"Unlike most of our other models the TSP100 series is a bit unique in that it is raster only meaning that it does not have the text formatting commands that our other printers do (ie, the printer just prints whatever receipt image you send it). Any formatting would be done in your application however you would like to do it before creating the image to send to the printer"
So this is clear that you have to maintain the column width, formatting, alignment etc everything by yourself.