Android Question Sending images with SocketServer and AsyncStreams

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Hi
I have done an App which uses a SocketServer object. It's purpose is to "Receive/Send" Ascii strings from/to a Client, and "Send" Camera pictures to it. For this task I "composed" the App using AsyncStreamsText, AsyncStreamsObject and CameraEx sources.
Despite the program works, I have some questions on this subject, to be sure of what I did:
1) I used both AsyncStreamsText (for Ascii strings I/O) and AsyncStreamsObject (for picture Output) because it seems to me that the second doesn't support sending/receivin Ascii strings.
2) The only way to send a Camera taken picture is to capture it, write it on a file and send this file.
3) I am using the NewSocket socket of the following code, to initialize both AsyncStreams objects. Is it correct?
B4X:
Sub Process_Globals ' code  is inside a service
    Private RemoteCaller As AsyncStreamsText
    Private SendPhoto As AsyncStreamsObject
    Dim ServerS As ServerSocket
    Dim nPort As Int : nPort=10250
End Sub
Sub Service_Create
   ServerS.Initialize(nPort,"ServerEvents")
End Sub
Sub Service_Start (StartingIntent As Intent)
   MyIp=ServerS.GetMyIP
   ServerS.Listen
End Sub
Sub ServerEvents_NewConnection (Successful As Boolean, NewSocket As Socket)
 If Successful Then
     RemoteCaller.Initialize(Me, "Server",NewSocket.InputStream,NewSocket.OutputStream) ' strings I/O
     SendPhoto.Initialize(Me,"Image") ' for sending picture
     SendPhoto.Start(NewSocket.InputStream,NewSocket.OutputStream)
  Else
     Msgbox(LastException.Message, "Error connecting")
End If
    'ServerS.Listen ' don't need continue listening to new incoming connections
End Sub
4) Monitoring the client, which is a C++ program, I see that the picture arrives in parts: first 4 bytes, then 54, then again 4 and finally various blocks of 1460 bytes (and a last one different). Does this subdivision mean anything or I must simply recompose the file on arrival?

Hope that my doubts are useful for other people too. Thanks for attention.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I used both AsyncStreamsText (for Ascii strings I/O) and AsyncStreamsObject (for picture Output) because it seems to me that the second doesn't support sending/receivin Ascii strings.
Why? The example clearly shows that you can send any object you like: https://www.b4x.com/android/forum/t...ceive-objects-instead-of-bytes.30543/#content

You should only use AsyncStreamsObject.

The only way to send a Camera taken picture is to capture it, write it on a file and send this file.
AsyncStreams allows you to send streams and arrays of bytes. It should be quite simple to modify AsyncStreamsObject and add support for memory streams.

Monitoring the client, which is a C++ program, I see that the picture arrives in parts: first 4 bytes, then 54, then again 4 and finally various blocks of 1460 bytes (and a last one different). Does this subdivision mean anything or I must simply recompose the file on arrival?
AsyncStreams composes the file for you. The last bytes are the checksum. You don't need to do anything special with this if you are using B4J.
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Thanks for the suggestions. I will try to apply them. There is only one further "doubt": I receive the picture with a C program; the file arrived, seems the same of that stored in the Android device, looking at its size. But Windows doesn't open it. Instead, IrfanView (a program specialized on graphic files) reads it. Saving it back with IrfanView, it is is much smaller. (From 59 kb to 32 kb). Talking of jpegs, it could be due to a different quality, but seems strange, having done nothing else than re-saving it. Thanks again.
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Hi Erel.
I have done some trials using AsyncStreamsObject. Unluckily, I don't see how easily to use it for strings. The example says that it is possible, but doesn't show how. As a matter of fact there is a key to assign. I, to make an experiment withou changing much in the example, tried to modify the:
B4X:
Sub btnSendNumber_Click
astreamO.WriteObject("simple value", 3)
End Sub
in
B4X:
Sub btnSendNumber_Click
astreamO.WriteObject("string", "aaaaa")
End Sub
Actually I don't see any documentation on this. (Please note that I use B4A exactly to "avoid" studying Android and Java, so perhaps I miss something very basic.)
As I wrote, I use a C client, not B4J. With the Microsoft C client, I must report you two facts: (1) I correctly send and receive strings, with AsynStreamTexts, while (2) with AsyncStreamObjects, even with the original sending of a number (simple value), I get two blocks of data: an initial 4 bytes and a very strange 164 Bytes second block. If I use the second version, for strings (my probably wrong modification), I again get a 4 bytes block, followed by a 94 bytes second one. The C client works fine with AsyncStreamTexts, so it should not be guilty (despite I don't exclude it). Probably some further elaboration has to be done on the arrived blocks? But how can we explain the 164 bytes for just the number 3? Sorry if I was pedant. Thanks for your attention.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You need to understand how AsyncStreams works.

Start with this tutorial: https://www.b4x.com/android/forum/threads/7669/#content

You can only use AsyncStreams.WriteStream (which is the base for AsyncStreamsObject) when both sides of the connection know how to work with this custom protocol. Generally this will only be the case if you implement both sides with one of the B4X tools.

Though there is an implementation of this protocol in C#: .Net FileTransfer - Implement AsyncStreams Prefix mode

The bottom line is that if you are implementing the server with C then shouldn't use prefix mode at all.
Implementing it with B4J will be much simpler.
 
Upvote 0
Top