two way UDP com with non max objects


    Feb 25 2012 | 12:30 pm
    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

    • Feb 25 2012 | 4:48 pm
      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
    • Feb 25 2012 | 5:22 pm
      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
    • Feb 26 2012 | 11:54 am
      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
    • Feb 27 2012 | 5:17 am
      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]