2 registered members (AndrewAMD, SBGuy),
987
guests, and 3
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
[solved]send_data
#452349
06/10/15 12:12
06/10/15 12:12
|
Joined: Mar 2012
Posts: 927 cyberspace
Wjbender
OP
User
|
OP
User
Joined: Mar 2012
Posts: 927
cyberspace
|
I need some help here with c#
I see I can only use send_data in c# instead of send_var , as i am new to whole network thing and stil new to c# , I first tried sending a simple string with send_data , it works fine .
now I wanted to try sending a structure with a string and a intptr in it , instead.
I tried marshalling the structure to intptr and sending it like that , then on the server/client event I tried marshalling the ptr back to a structure ,then reading the string and data from that .
However i cannot figure out where I went wrong because I get errors , so after a while I got rid of the code and now here I am asking for a bit of help in doing this correctly ,marshalling sending/receiving a struct and reconverting back with send_data , if you know how ?
Last edited by Wjbender; 06/11/15 20:33.
Compulsive compiler
|
|
|
Re: send_data
[Re: Ch40zzC0d3r]
#452366
06/10/15 15:28
06/10/15 15:28
|
Joined: Mar 2012
Posts: 927 cyberspace
Wjbender
OP
User
|
OP
User
Joined: Mar 2012
Posts: 927
cyberspace
|
I don't know what's up , I still think my marshalling was correct , and to be sure I wil rather test the Marshall back and forth between two simple functions, instead of across the network session ,my suspicion is that the memmory is the problem across the session because I am not using two separate computers ,instead I am running the c# compiled exe and setting the one as server and other as client while one of them I execute in debug mode to catch any unknown exceptions from the debug break , if my test idea works then my suspicion might be on the dot .
other than that it's useless to keep worring about send_data , I wil just move on to other tests .
Compulsive compiler
|
|
|
Re: send_data
[Re: Wjbender]
#452408
06/11/15 12:47
06/11/15 12:47
|
Joined: Mar 2012
Posts: 927 cyberspace
Wjbender
OP
User
|
OP
User
Joined: Mar 2012
Posts: 927
cyberspace
|
so i have tested the conversion across simple functions ,it works with no problem. i am fully able to read the data like this with one instance of the application which tells me my conversion is fine heres example code i used :
//this is a packet to be send by send_data_to
[StructLayout(LayoutKind.Sequential)]
public class packet
{
public string message;
}
//test marshal packet to intptr
public IntPtr to_intptr(object obj)
{
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
//test demarshal intptr to packet
public object to_struct(IntPtr ptr, Type t)
{
return Marshal.PtrToStructure(ptr, t);
}
//test recieve marshaled packet across function
public void recieve_packet(IntPtr ptr)
{
//get packet from intptr
packet my_packet = (packet)to_struct(ptr, typeof(packet));
Marshal.FreeHGlobal(ptr);
//a test message
network.network_events.mes = my_packet.message;
}
//test send packet across function
public void send_packet(packet ppacket)
{
//marshal packet to intptr
IntPtr ptr = to_intptr(ppacket);
//send intptr
recieve_packet(ptr);
}
.......
//inside my test loop
if (EngVar.key_3 && key3)
{
key3 = false;
//create packet
packet mypacket = new packet();
mypacket.message = "hello there";
//test send
send_packet(mypacket);
}
why do i convert ? because the wrapper needs the conversion to intptr because we do not use unsafe void* pointers in c# right. in the wrapper ,the native engine function send_data_to is wrapped like:
public static double send_data_to(ENTITY entity, IntPtr data, int size)
{
IntPtr entityPointer = IntPtr.Zero;
if (entity != null)
{
entityPointer = entity.getIntPtr();
}
return Conversion.varToDouble(NativeEngFun.send_data_to(entityPointer,data,Conversion.doubleToVar(size)));
}
and the native send_data_to which calls the dll function is:
[DllImport("acknex.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int send_data_to(IntPtr param0, IntPtr param1, int param2);
now ,that that's obvious and out of the way to whom-ever is reading. let me get to how i tried doing it across the network. heres my network test class file.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using AcknexWrapper;
namespace network
{
//client information container
class client_info
{
public string player_name;
public int id;
}//client information container
//list of clients information containers
static class connected_clients
{
public static List<client_info> client_ids = new List<client_info>();
}//list of clients information containers
//the packet to be send
[StructLayout(LayoutKind.Sequential)]
public class packet
{
public string message;
}
//marshalling & demarshaling helper
static class packet_convert
{
public static IntPtr to_intptr(object obj)
{
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
public static object to_struct(IntPtr ptr, Type t)
{
return Marshal.PtrToStructure(ptr, t);
}
}
//event handler for server & clients
static class network_events
{
public static string mes;
#region client_events
//client recieved an event
public static IEnumerable<int> on_client(IntPtr ptr)
{
//the server has send data to the client
if (EngVar.event_type == AcknexWrapper.Flags.EVENT_DATA)
{
//mes = AcknexWrapper.Native.Conversion.getStringFromIntPtr(ptr);
if (ptr != IntPtr.Zero)
{
packet my_packet = (packet)packet_convert.to_struct(ptr, typeof(packet));
network.network_events.mes = my_packet.message;
}
}
//client has joined session
if (EngVar.event_type == AcknexWrapper.Flags.EVENT_JOIN)
{
}
//client was dropped
if (EngVar.event_type == AcknexWrapper.Flags.EVENT_LEAVE)
{
}
yield return 1;
}//client recieved an event
#endregion
#region server_events
//server recieved an event
public static IEnumerable<int> on_server(IntPtr ptr,double id)
{
//the client has send data to the server
if (EngVar.event_type == AcknexWrapper.Flags.EVENT_DATA)
{
}
//client has joined session
if (EngVar.event_type == AcknexWrapper.Flags.EVENT_JOIN)
{
client_info this_client= new client_info();
this_client.id = (int)id;
this_client.player_name = AcknexWrapper.Native.Conversion.getStringFromIntPtr(ptr);
connected_clients.client_ids.Add(this_client);
}
//client was dropped
if (EngVar.event_type == AcknexWrapper.Flags.EVENT_LEAVE)
{
}
yield return 1;
}//server recieved an event
#endregion
}//event handler for server & clients
public class mp_session
{
//open a session on the server
public bool open_session(string session)
{
if (EngFun.session_open(session) > 0)
{
return true;
}
else return false;
}//open a session on the server
//connect to a session on the server
public bool connect_to_session(string session,string hostname)
{
if (EngFun.session_connect(session, hostname) > 0)
{
return true;
}
else return false;
}//connect to a session on the server
//close the session
public void close_session()
{
EngFun.session_close();
}//close the session
//send a string to client/s or server
//from client to server target must be null
//from server to all clients ,target must be null
//from server to the client that created the target entity
//The buffer size should not exceed about 1000 bytes - data packets above that size often get lost on transmission over the Internet
public void session_send_string(ENTITY target,string str)
{
if (str.Length > 0)
{
//The buffer size should not exceed about 1000 bytes
//data packets above that size often get lost on transmission over the Internet
if ((sizeof(char) * str.Length) < 1000)
{
EngFun.send_data_to(target, AcknexWrapper.Native.Conversion.getIntPtrForString(str), sizeof(char) * str.Length);
}
}
}
public void session_send_packet_to(ENTITY target, packet this_packet)
{
IntPtr ptr = packet_convert.to_intptr(this_packet);
int size=Marshal.SizeOf(this_packet);
//int size = Marshal.SizeOf(ptr);
EngFun.send_data_to(target,ptr,size);
Marshal.FreeHGlobal(ptr);
}
}
}
which i then call like this again in my main loop:
//test send string to clients
if (EngVar.key_3 && key3)
{
key3 = false;
//multiplayer_session.session_send_string(null, "hello there");
packet mypacket = new packet();
mypacket.message = "hello there";
multiplayer_session.session_send_packet_to(null, mypacket);
}
then i run one instance of the application in debug mode and the other from the exe file , so that i can set one as the server ,the other as the client. i then press 3 to send the packet to all clients ,then when the debugger breaks in to the on_client event ,it breaks at the demarshalling code with an exception of trying to read/write protected memmory at:
public static object to_struct(IntPtr ptr, Type t)
{
return Marshal.PtrToStructure(ptr, t);
}
which is taken from:
packet = (packet)packet_convert.to_struct(ptr, typeof(packet));
and i have tried everything i could think off , changing packing ,determining the size differently etc etc i cannot figure out whats going wrong , i am not even sure if the events are of the correct parameters , but sending a string instead of a packet works fine so i am assuming its correct , this is not to important but i would like to know whats wrong , although like i said i think its a memmory thing but i am not sure anymore . help is welcome .
Compulsive compiler
|
|
|
Re: send_data
[Re: Ch40zzC0d3r]
#452413
06/11/15 13:36
06/11/15 13:36
|
Joined: Mar 2012
Posts: 927 cyberspace
Wjbender
OP
User
|
OP
User
Joined: Mar 2012
Posts: 927
cyberspace
|
the send_string is the one that fully works , the session_send_packet_to is the one I am testing ,it successfully works until the data recieved event is triggered and I try to get the data from the intptr is where it fails with an exception , the freeing doesnt matter at this point I can comment it out and the result stays the same (same problem persists)
I do not really need to check if the intptr is zero because I check it in the event before calling the to_struct .
to me it seems like the intptr in the event parameter`s memmory is held and does not belong to me ? how am I going to test this weird theory I now have
Last edited by Wjbender; 06/11/15 13:40.
Compulsive compiler
|
|
|
Re: send_data
[Re: Ch40zzC0d3r]
#452422
06/11/15 17:10
06/11/15 17:10
|
Joined: Mar 2012
Posts: 927 cyberspace
Wjbender
OP
User
|
OP
User
Joined: Mar 2012
Posts: 927
cyberspace
|
I do have cheatengine but anyhow I debugged a little longer with visual studio and I see that the object is converted back on the event ,depending if I debug the client or server , but the message is empty .
now in the manual it says that:
The event function on the receiving PC receives a pointer to the buffer as its first argument. The buffer is only valid during the event function, and is deallocated afterwards.
"deallocated afterwards." 0_o
soo does this not tell me now that I cannot demarshal because for the engine to be able to "deallocate" it ,it would mean I cannot access that memmory (buffer) by demarshalling because demarshalling needs full access to that memmory anyway ?
I am fully confused now , does this require a memcpy equivalent ?
.....
Compulsive compiler
|
|
|
Re: send_data
[Re: Wjbender]
#452426
06/11/15 18:27
06/11/15 18:27
|
Joined: Oct 2011
Posts: 1,082 Germany
Ch40zzC0d3r
Serious User
|
Serious User
Joined: Oct 2011
Posts: 1,082
Germany
|
look its really easy:
char szData[256];
if(recv(sock, szData, 256, flags))
callback(szData, 256, id);
since this is all executed from a function its only on the stack! all the data will cleared after the engine function which called your callback returns which is kind of de-allocate. So when you ONLY use the stuff in your callback its fine, if you need it longer memcpy it to a global structure
Last edited by Ch40zzC0d3r; 06/11/15 20:12.
|
|
|
|