a = NetSend(hSock, "myDataKDFSLKE") print "NetSend - ";a
a = NetClose(hSock) print "NetClose - ";a call NetTerm
Sub NetInit open "mesock32" for DLL as #me End Sub
Sub NetTerm close #me End Sub
Function NetSetUDP() NetSetUDP = NetSetOption(1) End Function
Function NetSetTCP() NetSetTCP = NetSetOption(0) End Function
Function NetSetOption(opt) Calldll #me, "TCP_SetOption",_ opt as long,_ NetSetOption as long End Function
''''Function TCPOpen()'''''''''' Function NetOpen(address$,Port) Timeout=1000 calldll #me, "Open", address$ As ptr,_ Port As Long,_ Timeout As Long, re As Long NetOpen=re End Function
''''Function TCPReceive$()'''''''''' Function NetReceive$(handle) buffer=4096 all=0 calldll #me, "ReceiveA" ,handle As Long,_ buffer As Long,_ all As Long, re As long if re<>0 then NetReceive$ = winstring(re) End Function
''''Function TCPPrint()'''''''''' Function NetSend(handle,text$) calldll #me, "SendA", handle As Long,_ text$ As ptr,re As Long NetSend=re End Function
''''Function TCPClose()'''''''''' Function NetClose(handle) calldll #me, "CloseA",handle As Long,_ NetClose As Long End Function
I have been playing with it. On a Windows machine I would recommend that you get a copy of UDP Test Tool v3 This is an easy to use utility that makes it easy to set up a host or client to test your message passing.
On my machines I run Windows Defender and it manages my firewall(s). I had to allow both liberty.exe and UDP Test Tool access through my firewall before messaging would work. Use Windows help to add or amend these programs on the "allowed list"
I say firewall(s) because each machine needed set, I had assumed the firewall was a single beast lurking in my router. but not so.
I think because I have several devices on a wireless router that "localhost" is meaningless at my location. Each machine I have connected has its own local IP Press Windows Key + x choose command prompt and key in ipconfig
You will be shown info about your network, there will be an ipv4 value like 192.168.1.105 That is the machines local IP address and that is the address you will message to working locally. I have yet to try going out over the Net.
With the firewall fixed I can happily send messages from each local machine to the other.
Now my question, because I am completely new to all of this. The Liberty code at the moment ALWAYS awaits a response. It times out and stops. How to prevent that?
Also where to send the response? If I have the host set listening as 192.168.1.89 port 55000, running the code on the client with that data as the destination, the message is sent and received by the host. The client is 192.168.1.106 and while I know the client opens a random port to send the message how do I respond? Do I have to trap the incoming ip and port and respond to that?
Now having spent all of an hour or so reading here is my challenge. Why are we expecting a response? It is a connectionless protocol. Surely all we can set up is a host that listens and a client that sends. If the host has to respond it must surely act as a client and "know" the host ip and port to send the response to.
So my question now is how do we use Chris's code to act as host and listen on a specific port?
Ah, I missed the announcement somehow. So we have a new LBNet resource to play with. I think the issue with mesock32.dll is that it could not cope with chr$(0) which it saw as a string/message terminator. If we could round off the mesock32.dll thread with an example of listening that would close everything off here.
We have a function header for a UDPListen call in Visual Basic: '====================================================================== 'Function: UDPListen 'Variables: ' hwnd: long -- specifies the windows handle: this is required since data is sent to the 'specified window handle. 'lPort:long -- Specifies the port to listen on 'lconnection:long -- Specifies the number of connections allowed to the server. 'ltimeout:long -- Specified a timeout: If 0, the Timeout will be set to 10 seconds. 'NOTE: ltimeout is represented by milliseconds, so 10 seconds would be represented as '10000 'Returns: ' Long: 0 if successful -- error number if failed. '======================================================================= Declare Function UDPListen Lib "mesock32.dll" Alias "UDPListen" _ (ByVal hwnd as long, _ byval lPort as long, _ byval lconnection as long, _ byval ltimeout as long)) As Long
Because it asks for a window handle, we can infer that it somehow delivers the information using a window message, which means we need to a) open a window to handle it, and b) use WMliberty to extract the needed information.
Currently, I have no idea what format the information comes in as.
'======================================================================== ' These are the messages that the listening functions use to pass data from the library to the app. '======================================================================== Const WM_USER = &H400 Const TCP_MESOCK = WM_USER + &H7CD Const UDP_MESOCK = WM_USER + &H7D1
These are the window messages(in particular, UDP_MESOCK) we'd have to trap with WMLiberty.
There are links to sample server code, but the Visual Basic link doesn't work, and the IBASIC link is incomplete.
So, I have no idea how IBASIC works, but I know general program and Windows structure well enough to maybe figure it out.
Here's the code for receiving the MESOCK message:
select @CLASS case @UM_MESOCK ' Our message has come in, time to process. ' Format for the processed message is as follows: ' wparam == length of data sent (via pointer) ' lparam == pointer to data tString=Space$(@CODE) pPtr = tString RtlMoveMemory(pPtr, @QUAL, @CODE) setcontroltext(d1, 2, getcontroltext(d1, 2) + chr$(13) + chr$(10) + #pPtr)
That's... a problem. While it would work in LB just fine, (and having an explicit size pointed to means no data would get lost), it also means we get no information as to who sent the data, meaning we can't send anything back. This goes for both TCP AND UDP connections.
I honestly would've expected that it just passed in a socket handle to wParam or lParam, and you'd use the mesock Receive() and Send() calls to receive and send data over that socket. I don't know what to do with this.
There is no other useful information from this - no patameters passed or values returned, for example. In LB code I have seen only open(a) close(a) send(a) and receive(a) actually called, although some code mentions TCP_SetOption but does not call it.
In other code (lua I think) I have come across references to SetOption, and it seemed to take one integer parameter which was a combination of flag constants, eg. BROADCAST, MULTICAST, KEEP_ALIVE and numerous others. If anyone can find a header file that shows these actual values, and has a good idea what they really mean, then that might be worth experimenting with. But not me, I have no real experience with networking.
Post by Chris Iverson on Feb 9, 2020 18:58:28 GMT -5
Mesock's TCP_SetOption() is different from the winsock/sockets setsockopt() function(which is what handles the functions you're speaking of). According to mesock's documentation, the TCP_SetOption() call is only used to change into UDP mode(which is what my code above uses it for).
And yeah, TCPListen()/UDPListen() are what are used to create a TCP/UDP server, but without the ability to send data back, they can ONLY ever receive.
I'm actually planning on trying to disassemble the DLL at some point to figure out if there's any more information on how TCP/UDPListen() are used, and if they can actually send data back. (I'd try to contact the author, but considering "Terry Reese" can't be found in any of the modern Oregon State University systems, and the only contact information was an OSU email address, I think that option isn't available anymore.)
EDIT: Actually, nevermind the last part. I may have found him.
I don’t think the concept of “sending data back” exists for UDP. So there is no way for a client to get feedback unless it opens a host service and the other host knows that address. So duplex communication might be possible but it isn’t in the design. We just need a simple listener host.
Post by Chris Iverson on Feb 10, 2020 12:25:35 GMT -5
The concept exists for all network communication, by the very nature of sockets themselves. If it's a connection-based socket(usually TCP), the socket itself will contain the endpoint information for both ends of the connection, and this gets established upon initial connection. For UDP, the receiving side will get the address information at the same time it receives a packet, and it can use that address information to send data back. (You'll remember in the python script, how it shows the IP address and port of every client it received data from? That's how).
In sockets terms, the when the client side calls connect(), and the server-side calls accept(), the SOCKET on both endpoints contains the address/port information for both ends, and then you use send()/recv() to transmit data, which works based on the underlying connected socket.
For a connectionless socket(i.e. UDP), you don't use connect()/accept(), and you get a new set of transmission functions, sendto()/recvfrom(). When acting as a "server", you just listen on the UDP socket to see if anything's there. If something's there, a recvfrom() will receive the data, as well as the remote endpoint information. You can then pass that information into sendto() to send a response back.
The mesock design prevents that from happening for BOTH TCP AND UDP, because it does not give you any information as to which connection the data came from. Therefore, it's impossible to send a response back, no matter which protocol you use.