SOLVED Sending an image through network

Antikore

Member
I've been playing around with GMS 1.4 native networking the last days and I'm doing pretty good, but the challenge I'm facing now is so much more complicated than I've expected.
My idea is to send an small image (240 x 135) from the server to the client. As I'm doing my tests on my own computer, I just want the server to take a .png from the game's folder and the client create the same .png with another name on that folder. However, at the end the client is only creating a fully transparent 240 x 135 png file. Here is the current code after multiple changes to see what may work and what doesn't

GML:
// Asynchronous event for networking event. This is the piece of code on network_type_connect
global.socket_to_send = async_load[? "socket"];
ds_list_add(global.players, global.socket_to_send);

var image = sprite_add("laconcha.png", 0, false, false, 0, 0);

var w = sprite_get_width(image);
var h = sprite_get_height(image);

sf = surface_create(w, h);

surface_set_target(sf);

// Looks like this is working even outside of the draw event, anyways I tried to do it on the draw event and the result is the exact same.
draw_sprite(image, 0, 0, 0);

surface_reset_target();

// Made this just in case the sprite wasn't drawing at all in the same frame.
alarm[0] = 1;
GML:
// Alarm 0 on the server controller, it writes 3 as the type of message, adds the surface
// and then sends it as a packet, then frees the surface.
if (!surface_exists(sf)) exit;

buffer_seek(global.buffer, buffer_seek_start, 0);
buffer_write(global.buffer, buffer_u8, 3);

// At this point the surface with the image is correct
// surface_save(sf, "coso.png");

buffer_get_surface(global.buffer, sf, 0, 0, 0);

network_send_packet(global.socket_to_send, global.buffer, buffer_tell(global.buffer));

surface_free(sf);
GML:
// The client packet handler, this is what executes when the packet type is 3
// as it was before established on the server
surface = surface_create(240, 135);
buffer_set_surface(buffer, surface, 0, 0, 0);

// Did this for the same reason as the alarm on the server
alarm[0] = 1;
GML:
// Client controller alarm 0, saves the surface and frees it again.
if (!surface_exists(surface)) exit;
surface_save(surface, "tonasso.png");
surface_free(surface);
I searched on the Internet for similar issues, but I only found a post that the issue was actually irrelevant and the solution wasn't explanatory for my issue.

using Windows 10 and GameMaker: Studio v1.4.1804

Just in case these are the buffer specs
GML:
var buffer_size = 65535;
var buffer_type = buffer_grow;
var buffer_alignment = 1;
 

Mert

Member
This is probably happening because the image file is sent in more than 1 tcp package. You must manually read and collect the chunks of the data in a variable - and then create the sprite with it.
 

Antikore

Member
Why don't you just load laconcha.png in directly as a buffer, rather than involving sprites texture pages and surfaces
I have already tried that I think, the result was a corrupt .png file full of NUL characters

EDIT: Checked, I confirm that happens what I'm saying
 
Last edited:

Antikore

Member
This is probably happening because the image file is sent in more than 1 tcp package. You must manually read and collect the chunks of the data in a variable - and then create the sprite with it.
I think I tried that already, but I don't know if in the correct way. I tried reading the png as a text file and sending it to the client as a list of lines of a text file, then recreating it again, but some characters were omitted so it didn't work :/
 

Pyrusman

Member
How is this issue solved? I do not see the resolution in the thread. Also, any idea of how to pass an image from one client to another client (or server). (e.g., sharing a captured pic or custom avatar image)
 

FrostyCat

Member
There was no resolution because the original poster tried two completely pointless things in turn, the first putting the whole file into one packet, and the second reading a PNG as a text file. The first basically ignores the concept of the MTU, and the second is sheer ignorance of basic file formats.

There is nothing magical to this, Mert said what needed to be said. You divide the file into binary chunks (NOT line-by-line chunks), then send them over in a back-and-forth exchange between the two parties. Something like this:
  • A: I am about to send "foo.png" that is N chunks long.
  • B: OK, I confirm to be receiving "foo.png". Start sending.
  • A: Sending chunk 1 of 1024 bytes.
  • B: I got chunk 1 and noted it down in a buffer. Please send chunk 2.
  • A: Sending chunk 2 of 1024 bytes.
  • B: I got chunk 2 and noted it down in a buffer. Please send chunk 3.
  • ...
  • A: Sending chunk N of X bytes.
  • B: I got chunk N and noted it down in a buffer. Transmission complete, writing the buffer into the "foo.png" and closing.
  • A: Closing transmission of "foo.png".
The exact details depend on how your existing protocol is designed, but in any case, it will be a back-and-forth exchange, no one-line answers here.
 
There was no resolution because the original poster tried two completely pointless things in turn, the first putting the whole file into one packet,
I actually wasn't suggesting sending the whole file over the network, I would suggest fragmenting it. I can see that's not clear from my post and evidently missed the notification when OP replied. Either way, why is this not a good idea (assuming both methods are not good)?
 

FrostyCat

Member
I actually wasn't suggesting sending the whole file over the network, I would suggest fragmenting it. I can see that's not clear from my post and evidently missed the notification when OP replied. Either way, why is this not a good idea (assuming both methods are not good)?
Fragmenting it is the solution, and your suggestion was correct. The problem was that the original poster completely ignored your advice the first time (i.e. sending the entire raw surface), and fragmented by the wrong criteria the second time (i.e. splitting a PNG file by lines like a text file instead of n-byte chunks like a binary file).
 
Top