two way UDP com with non max objects
this is a followup to a thread on the dev board > https://cycling74.com/forums/udp-sendrecieve-to-non-max-objects
im still having problems with ports and non max UDP comm
when i use processing (OSCp5 lib) OSCarguments example http://i.imgur.com/8Ijui.png (code pic)
i get this (via packet sniffer wireshark)
http://i.imgur.com/2ufqs.png (wireshark capture)
here i set a "receive" on port 6000, and a "send" on port 5656
in arduino (+ethrent shield) i set receive to port 5656 and
send port to be auto assigned via
`
// send a reply, to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
http://i.imgur.com/of1td.png (full code)
on max my udpsend src port is always different, it sends but max will not receive data
http://i.imgur.com/6sod8.png (wireshark capture)
cant i set the destination port explicitly?
how can i bind udpreceive to that auto-generated port?
[udpsend 10.0.0.55 5656]
even when exclipctly targeting a port i dont get anything.
i tried mxj net.udp.send, sadam.udpSender object. all with same outcome.
windows x64, max6.04
Hi,
two-way UDP (or TCP) communication is a bit harder, as normally you need to let the socket open during the entire transaction. Max objects that do networking (udpsend/receive, mxj net stuff and my sadam.* objects) won't do that for you, as they all (1) open a socket, (2) send the data and then (3) close the socket. I'm developing a TCP object that would let the socket open (therefore, which would do two-way communication), but I can't tell when it would be ready. If you know a little bit of C, the easiest way would be to do a simple two way external for the actual purpose, or wait for a general-purpose tool.
HTH,
Ádám
first thanks for your objects, and especialy for cross compiling to windows. a hassle and i apprciate that
as for twoway, i will find something, If you have some snippets for that c part i would love to take a look
Hi,
well, the best thing you can do in this case is a google lookup for standard Server-Client code snippets for Windows. However, before doing so, you have to think a little bit about your network setup. As in each two-way network scenario, there must be a server (which runs during all the time in the background and for each incoming requests it starts a new thread for managing the communication) and a client (which would initiate and terminate the communication with the server in the proper way). So, the first thing is, you need to know who is the 'server' and who is the 'client' in your case (unfortunately I don't know neither Processing nor Arduino, so I've no idea of how networking works there). If you're lucky, then they would act as servers, in which case you don't need to take care of the server tasks in Max, you'd just need to implement a simple client.
Here's the code that I'm using in [sadam.udpSender]
. Feel free to use it and extend it according to your needs. This is not a trivial task, however - you'd need to understand what you're doing anyway.
The ERR_*
macros are just error messages that I define earlier, you can ignore them. The rest of the definitions are in the header files that you need to include (in the WIN_VERSION
and MAC_VERSION
blocks):
#ifdef WIN_VERSION
#include
#endif
#include
#include
#include
#include
#include "ext.h"
#include "ext_obex.h"
#include "ext_globalsymbol.h"
#include "ext_systhread.h"
#include "sadam.stream.h"
#ifdef MAC_VERSION
#include
#include
#include
#include
#endif
And here is the function that actually sends the data:
void UDPSender::sendData ( std::vector < unsigned char > & data ) {
struct sockaddr_in localAddress;
struct sockaddr_in serverAddress;
struct hostent * hPrt;
t_symbol * localHost;
unsigned char * buffer;
unsigned char * iterator;
unsigned long localPort;
unsigned long size;
long result;
#ifdef WIN_VERSION
SOCKET socketDescriptor;
WSADATA wsaData;
#else
int socketDescriptor;
#endif
if ( data.empty ( ) ) {
return;
}
localHost = host;
localPort = port;
// Create socket
#ifdef WIN_VERSION
if ( ( result = WSAStartup ( MAKEWORD(1, 1), & wsaData ) ) != 0 ) {
if ( verbose ) {
object_error ( ( t_object * ) this, ERR_WSA );
}
outlet_int ( outlet, result );
return;
}
socketDescriptor = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( socketDescriptor == INVALID_SOCKET ) {
WSACleanup();
#else
socketDescriptor = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( socketDescriptor < 0 ) {
#endif
if ( verbose ) {
object_error ( ( t_object * ) this, ERR_SOCKET, localHost->s_name );
}
outlet_int ( outlet, errno );
return;
}
// Bind port
localAddress.sin_family = AF_INET;
localAddress.sin_addr.s_addr = htonl ( INADDR_ANY );
localAddress.sin_port = htons ( 0 );
if ( bind ( socketDescriptor, ( struct sockaddr * ) & localAddress, sizeof ( localAddress ) ) != 0 ) {
if ( verbose ) {
object_error ( ( t_object * ) this, ERR_BIND, localPort, localHost->s_name );
}
outlet_int ( outlet, errno );
#ifdef WIN_VERSION
closesocket ( socketDescriptor );
WSACleanup();
#else
close ( socketDescriptor );
#endif
return;
}
// Get server address
hPrt = gethostbyname ( localHost->s_name );
if ( hPrt == NULL ) {
result = -1;
if ( verbose ) {
object_error ( ( t_object * ) this, ERR_HOST, localHost->s_name );
}
outlet_int ( outlet, result );
return;
}
serverAddress.sin_family = hPrt->h_addrtype;
memcpy ( ( char * ) & serverAddress.sin_addr.s_addr, hPrt->h_addr_list [ 0 ], hPrt->h_length );
serverAddress.sin_port = htons ( localPort );
// Send data
size = data.size ( );
buffer = new unsigned char [ size ];
iterator = buffer;
for ( std::vector < unsigned char >::iterator i = data.begin ( ); i != data.end ( ); ++ i ) {
* iterator ++ = * i;
}
iterator = buffer;
result = sendto ( socketDescriptor, ( const char * ) iterator, size, 0, ( const struct sockaddr * ) & serverAddress, sizeof ( serverAddress ) );
if ( result < 0 ) {
if ( verbose ) {
object_error ( ( t_object * ) this, ERR_SEND, host->s_name, localPort );
}
outlet_int ( outlet, result );
}
delete [ ] buffer;
outlet_int ( outlet, 0 );
#ifdef WIN_VERSION
closesocket ( socketDescriptor );
WSACleanup();
#else
close ( socketDescriptor );
#endif
}
}
Hope this helps,
Ádám
thanks for the indepth
EDIT:
note to self, if packet sniffer acknowledged shipped packet,
and you still don't get anything in max, *check your FIRWALL*
all is well, two way comm is working,
wish all my problems could be solved with a toggle
[shamE shaME shAME sHAME SHAME]