Freelance Ethernet Rec/Send and TCP module
I'd like to use ethernet module which is avaiable on DCP02 to communicate with external C program which would run somewhere on the network. I've written some test client/server programs in ms visual (sending some raw data), but had no luck with establishing connection with software emulator (one which was aviable on some demo CD).
In HM, I've placed SR_SRTCP and SR_RNDEV interface. In FBD program i use Receive Module from TCP/IP Send and Receive under Blocks menu. Error states in HW are somewhat confusing, sometimes there's (1) network layer error sometimes (23) connection timeout and (25) no connection, all of them happens when i tried to establish connection and even if I don't. I've also tried different client/server settings. Anyway is there any receipe to do this kind of connection ? Should the frames contain some special "magic" data?
I should add that netstat -a shows open ports which i configure in HW, so there's something alive there.
Any help would be greatly appreciated.
Ethernet send/receive works fine between controller/controller or even I tried between emulators. Catch here is set configuration parameter at source(Server) and destination(Client) to complement each other @ HW SR_SRTCP as well as @ FBD block SR_USEND/SR_URECV
I recommend first establishing eth send/rec. communication between two emulators running in different pc to get understanding. Once it is done try to add your external C program application. Find attached document with configuration for establishing eth send rec between two emulators.
Hope it helps to you..
Thanks for very quick response. It took me awhile to set up test environment, and here's what I've found.
Your suggestion to use 2 emulators worked. I managed to establish connection. It wasn't perfectly reliable, on physical link disconnection and reconnection, data transmission stops or there are errors suggesting lack of resources , but that's not the big issue for me now.
Next thing I've done was sending raw data between 2 emulators and it didn't work so as sending raw data to external C program. I've used wireshark to sniff a bit.
I've treated EMU as a server. Client sends SYN, server responds with SYN/ACK, client goes with ACK, connection established and...... that's it. When I try to read from socket nothing happens, when I write to socket, server goes SYN,RST and that's the end. I don't recall exactly what happend when I switched client with server in terms of TCP sniffing, but nothing that worked happend ;-)
I assume server needs some kind of request, because how Freelance would interpret the data that comes, when we have several blocks etc.
But what that would be ?
Thanks in advance for any comments on this.
I have idea about Ethernet S/R between two freelance controllers but never had chance to communicate with external code base application, Hence I do not have idea with this I apologies for that.
Nevertheless as I see you are using some external C program, If you get some problem in s/r communication, You can try with DMS API as alternate to get interface with freelance check details @ this location,
Hope it helps to you.
It's been a while, but I finally made some progress.
I don't know exactly what I did wrong, but know it all seems to work.
So here are two scenarios i tested:
1)Sending data from process station. Insert UDP send module. Make sure remote udp port is the same as is your program's port. You may also mark send raw data, in that case there won't be freelance's header in a frame).Next step, put SR_USEND function block(s), mark autorequest, pack the data... and that's all. Packets start flying.
Windows uses winsock so we initiliaze it, than open socket and bind, and may start receving data by the recvfrom function.
2)Receving data from external C program or some other TCP/IP equipment. Here comes the freelance header and some magic numbers. Big Thanks to HenkelD, who posted description of the header in some other thread. I recommend to read it. But, to the point. From the freelance CBF side there's nothing trublesome, you just have to make sure IPs and port numbers are correct, and remember the IDs of SR_URECV function blocks you use (you will put those IDs in the header later). Structure is similar to first program but we use sendto function (because of sendto function you probably don't have to bind the socket, but I didn't check that). Using description from HenkelD we create the structure for header and data and send it to the process station.
Sample source code for sending one variable INT (unsigned short in C) to he block of ID 1 on PS:
// UDP_F2Ksend.cpp : Defines the entry point for the console application.
// UDPTest.cpp : Defines the entry point for the console application.
Simple udp client
Silver Moon (firstname.lastname@example.org)
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define SERVER "192.168.1.56" //ip address of udp server
#define BUFLEN 1400 //Max length of buffer
#define PORT 55551 //The port on which to listen for incoming data
#define MAGIC_NUMBER1 6782719
#define MAGIC_NUMBER2 19111959
unsigned short cHeaderLen;
unsigned short nDataLen;
unsigned long ulMagicNumber1;
unsigned long ulMagicNumber2;
unsigned short usSeq;
unsigned short usId;
unsigned short usCmd;
unsigned short usData;
struct sHeader sHDR1;
signed int siData;
signed int siData1;
int _tmain(int argc, _TCHAR* argv)
sMessage1.sHDR1.ulMagicNumber1 = MAGIC_NUMBER1;
sMessage1.sHDR1.ulMagicNumber2 = MAGIC_NUMBER2;
sMessage1.sHDR1.usSeq = 12351;
sMessage1.sHDR1.usId = 1;
sMessage1.sHDR1.usCmd = 0;
sMessage1.sHDR1.usData = 0;
sMessage1.siData = 0;
struct sockaddr_in si_other, client;
int s, slen=sizeof(si_other);
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
printf("Failed. Error Code : %d",WSAGetLastError());
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
printf("socket() failed with error code : %d" , WSAGetLastError());
//setup address structure
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
//bind(s, si_other, 5);
//connect(s, (SOCKADDR*)&si_other, slen);
bind(s, (SOCKADDR*)&si_other, sizeof(si_other));
// printf("Enter message : ");
printf("\nProba wysylu: %d\n", n);
//send the message
if (sendto(s, (char*)&sMessage1, sizeof(sMessage1) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
printf("sendto() failed with error code : %d" , WSAGetLastError());
//receive a reply and print it
//clear the buffer by filling null, it might have previously received data
//try to receive some data, this is a blocking call
//if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
//printf("recvfrom() failed with error code : %d" , WSAGetLastError());
//for(int m=0;m<50;m++) printf("0x%x ",(unsigned char)buf[m]);