Posted: 20th Nov 2023 15:39
Building on my network/socket example, I'm trying to demonstrate sending data objects larger than the packet size limit of 1.4kb. As far as I can tell, that part works. I'm sending an image by create a memblock and sending the bytes over to the client (same as the server in this case) and creating a new memblock to write the data. Then I create an image from the memblock and finally create a sprite. The image dimensions seem to carry over just fine, but for some reason the color data is all zeros. The bytes are sent the exact same way, so I'm not sure why the first 12 bytes are perfectly fine but the rest are not. I'm not sure if its because sockets send signed bytes when everything else in agk using unsigned or what.


+ Code Snippet
// Project: socket 
// Created: 2023-11-17

SetErrorMode(2)
SetWindowTitle( "socket" )
SetWindowSize( 1024, 768, 0 )
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
//SetSyncRate(30, 0)


// The listener is our server.  In this example, we will listen for incoming 
// connections on the localhost at port 8080
listener = createSocketListener("127.0.0.1", 8080)
// This will be the server's connection to connected client. In a true server
// this would be an array as you'd potentially have multiple clients connecting.
// For this example, we'll only deal with a single client, ourself.
conn = 0
// The client's connection to the server.
client = 0


fromServer$ = ""
fromClient1$ = ""
fromClient2$ = ""

msg$ = "Client disconnected."

#CONSTANT DATA_MEMBLOCK_IMG = 2


// Data coming from server
img = loadImage("powercell64.png")
m = createMemblockFromImage(img)
mSize = getMemblockSize(m)
sendingMemblock = 0
mPointer = 0


// Used on client
doingLargeThing = 0
clientMem = 0
cPointer = 0
clientImg = 0



do
    
    
    // Free the sockets on hitting ESC and exit the app
    if getRawKeyPressed(27) = 1
		deleteSocketListener(listener)
		deleteSocket(conn)
		deleteSocket(client)
		end
	endif
	
	
	// Press 'c' to connect the client to the server
	if getRawKeyPressed(67) = 1 
		client = connectSocket('127.0.0.1', 8080, 3000)
	endif
	
	
	if sendingMemblock = 1
		//SendSocketByte(conn, mPointer)
		packSize = mPointer + 1000
		if packSize > mSize then packSize = mSize-1
		for i = mPointer to packSize
			SendSocketByte(conn, getMemblockByte(m, mPointer))
			t = getMemblockByte(m, mPointer)
			inc mPointer
		next i
		flushSocket(conn)
		if packSize = mSize-1
			sendingMemblock = 0
			//SendSocketString(conn, "END")
			//flushSocket(conn)
		endif
	endif
	
	
	
	// Press 'spacebar' to send timestamp from server to the client
	if getRawKeyPressed(32) = 1
		// Make sure the client is still connected
		if getSocketConnected(conn) = 1
			// Send our data to the buffer
			//sendSocketString(conn, str(GetMilliseconds()))
			
			if sendingMemblock = 0
				sendingMemblock = 1
				
				SendSocketByte(conn, DATA_MEMBLOCK_IMG)
				SendSocketInteger(conn, mSize)
				
				// Flush the data.  Until you flush the socket, anything
				// you write to the buffer will sit there. 
				// Caution:  Once the buffer has reach 1.4KB, it will automatically flush the buffer.
				flushSocket(conn)
			endif
		endif
	endif
	
	
	
	// Press 's' to send data from the client to the server
	if getRawKeyPressed(83) = 1
		// Check client is still connected to server
		if client > 0
			if getSocketConnected(client) = 1
				h$ = hex(val(fromServer$))
				// While we had the server send us only 1 string, 
				// we're going to have the client send 2 strings back to the server.
				// First string will take the timestamp this client received from the server and
				// convert it to hex.  The second string will be the hex value encoded in base64.
				sendSocketString(client, h$)
				sendSocketString(client, hexToBase64(h$))
				flushSocket(client)
			endif
		endif
	endif
	
	
	
	
	// Until we have a client connected, the server will
	// continue to listen for incoming connections. You
	// would modify this to always listen if your server
	// is to handle multiple clients at once.
	if conn = 0
		lc = getSocketListenerConnection(listener)
		if lc > 0 then conn = lc
	else
		// If server is connected to a client, listen for data from that client
		if getSocketConnected(conn) = 1
			if getSocketBytesAvailable(conn) > 0
				// This example expects 2 strings sent from the client
				fromClient1$ = getSocketString(conn)
				fromClient2$ = getSocketString(conn)
			endif
		endif
	endif
	
	
	
	
	// The client listens for incoming data from the server
	if client > 0
		// Make sure client is still connected to the server
		if getSocketConnected(client) = 1
			
			msg$ = "Connected to server at " + getSocketRemoteIP(client)
			
			// Check if any data is awaiting to be read
			if getSocketBytesAvailable(client) > 0
				// In our example, we expect to get a string
				//fromServer$ = getSocketString(client)
				
				// Not pending any large/chunked transfers
				if doingLargeThing = 0
					code = getSocketByte(client)
					
					if code = DATA_MEMBLOCK_IMG
						clientMemSize = getSocketInteger(client)
						clientMem = createMemblock(clientMemSize)
						cPointer = 0
						doingLargeThing = 1
					endif
				else
					while getSocketBytesAvailable(client) and cPointer < clientMemSize
						setMemblockByte(clientMem, cPointer, getSocketByte(client))
						inc cPointer
						if cPointer >= clientMemSize
							doingLargeThing = 0
							clientImg = createImageFromMemblock(clientMem)
							cs = createSprite(clientImg)
							
							exit
						endif
					endwhile
					
				endif
			endif
		else
			msg$ = "Client disconnected."
		endif
	endif
	
	
	
	print(t)
	print(msg$)
	print("")
	print("Client received message from server: "+fromServer$)
	print("")
    print("Server received client's response 1: "+fromClient1$)
    print("Server received client's response 2: "+fromClient2$)
    print(str(cPointer) + " / " + str(clientMemSize))
    
    p = floor(((cPointer+0.0) / clientMemSize) * 100)
    
    if clientMem > 0
		print(str(p)+"% completed.")
		
    endif
    if cs > 0
		setSpritePosition(cs, getRawMousex(), getRawMouseY())
		print(getSpriteWidth(cs))
    endif
    
    Sync()
loop
Posted: 20th Nov 2023 16:00
Alright, so I changed the code to send integers instead of bytes. I know reading the bytes from a memblock image will put the components in opposite order as if reading just the integer (due to endian), but as long as I read and write those bytes the same way, that shouldn't matter. So I think the problem is with sockets sending SIGNED bytes, for whatever stupid reason.
Posted: 20th Nov 2023 17:49
You have mpointer in your for loop but increasing it at the same time in the for loop.

This will have undesired affects

Maybe change line 72 on the getmemblockbyte from mpointer to " i " instead

+ Code Snippet
   if sendingMemblock = 1
        //SendSocketByte(conn, mPointer)
        packSize = mPointer + 1000
        if packSize > mSize then packSize = mSize-1
        for i = mPointer to packSize.     //***** Mpointer here
            SendSocketByte(conn, getMemblockByte(m, mPointer)). // Change mpointer to i
            t = getMemblockByte(m, mPointer) // not sure what this is doing in this for loop
            inc mPointer // but increasing it here, remove  ******
        next i
        flushSocket(conn)
        if packSize = mSize-1
            sendingMemblock = 0
            //SendSocketString(conn, "END")
            //flushSocket(conn)
        endif
    endif





To

+ Code Snippet
   if sendingMemblock = 1
        //SendSocketByte(conn, mPointer)
        packSize = mPointer + 1000
        if packSize > mSize then packSize = mSize-1
        for i = mPointer to packSize.     
            SendSocketByte(conn, getMemblockByte(m, i))
            t = getMemblockByte(m, i ) // I'm not sure what this is doing you don't use " t " in your full snippet
            
        next i
        flushSocket(conn)
        if packSize = mSize-1
            sendingMemblock = 0
            //SendSocketString(conn, "END")
            //flushSocket(conn)
        endif
    endif





Programming 1 o 1

We shouldn't increase a value that is embedded in a for loop
and increase inside a for loop cause it will just skip values left right and centre and produce undesired results.

Maybe you just probably missed that.

To test the send byte - maybe test that command by sending a few single bytes manually to prove if that command works or not.
Posted: 20th Nov 2023 18:52
ahh, crap. rookie mistake! The more I look at that loop now the more I see wrong with it.

It's strange that when I changed it to use an integer and step 4 it worked.
+ Code Snippet
if sendingMemblock = 1
     
     packSize = mPointer + 1000
     if packSize > mSize then packSize = mSize-1
     for i = mPointer to packSize step 4
         SendSocketInteger(conn, getMemblockInt(m, mPointer)).
         inc mPointer, 4
     next i
     flushSocket(conn)
     if packSize = mSize-1
         sendingMemblock = 0
     endif
 endif


Regardless, I need to rewrite this loop without being a complete idiot.
Posted: 20th Nov 2023 18:55
There is the steps of 4 to a PNG too. Happy you got your integers 4 to bytes 1 correct.

I'm dumbfoundered though that it still worked

I've got to change my teachers lol

But I'm all for redundancy coding
Posted: 20th Nov 2023 19:05
Hmm in theory this should be working. I do get an image but it's skewed, so something isn't lining up correctly. This was suppose to be a simple 10min project.......

Nevermind, another stupid typo. This works fine now. And I'm going to lunch before more brain cells die today.

+ Code Snippet
	if sendingMemblock = 1
		packSize = mPointer + 1000
		if packSize > mSize-4 then packSize = mSize-4
		// Loop through the next 1000 bytes, writing integers (hence the step 4)
		for i = mPointer to packSize step 4
			SendSocketInteger(conn, getMemblockint(m, i))
		next i
		mPointer = packSize+4
		// Send the data
		flushSocket(conn)
		// If we've sent all the memblock data
		if packSize+4 >= mSize
			sendingMemblock = 0
		endif
	endif
Posted: 20th Nov 2023 19:07
Don't forget your 12 bytes at beginning... Add 12

Edit

Forget me too, you need to send the full menblock Inc width and height. I forget your sending data over to a client

I'm happy you sussed it
Posted: 20th Nov 2023 19:09
The 12 byte header doesn't matter, I'm sending all the bytes from the memblock in order and they'll be written on the receiving end in the same order. The loop remains agnostic about what's being sent, only the receiving end really needs to know it's an image so it knows how to convert the memblock back.
Posted: 20th Nov 2023 19:15
Thank you for your help phaelax, it will help lots of others on how to do it