softweng
May 25th, 2001, 12:03 PM
I am trying to create a Class that can be used to communicate with a device using Modbus TCP protcol.
Basically you just send a command out on the TCP/IP connection in a certain format.
I have a C++ example and an OCX written by someone else that can do this. I don't know that
much about C++ but it is pretty simple to do. You build a command string and send it out and wait for a response. The C++ and OCX work fine.
I have a packet sniffer and looked at the data inside the packet and it is formated correctly (Using the C++ OCX).
when I try to send the command string in the same format the winsock control formats it to hex and then the command is wrong. If I sniff the packet
from my class the data is not correct. Is there a way to stuff the command string right into the
TCP/IP packet without it reformatting the data?
the command looks like this "00000000000601040000000A" it is in hex. It should look like this in the packet:
"00 00 00 00 00 06 01 04 00 00 00 0A"
But when I send the command it puts it into the packet like this:
"30 30 30 30 30 30 30 30 30 30 30 36 30 31 30 34 30 30 30 30 30 30 30 41"
I cannot figure out how to do this. If anyone has any Ideas or knows something about Socket Programming
I would appreciate some help. I am a VB programmer that does not know much about C++ and how it passes data to a TCP socket. I have
included here the C++ sample I found if anyone can tell me how to do the same in VB it would be a life saver.
Thanks for any help you can provide!!!!!!!
Here's the C++ code Sample. I have the whole OCX project in C++ too if it would help.
// test1.cpp - Win32 console app to read registers
// ============================================================
// test1.cpp 5/23/97
// example Win32 C++ program to read registers from PLC via gateway
// compile with BC45 or BC50
// default settings for Win32 console app
// empty DEF file
#include <winsock.h>
#include <stdio.h>
#include <conio.h>
int main(int argc, char **argv)
{
if (argc<5)
* {
*** printf("usage: test1 ip_adrs unit reg_no num_regs\n"
*** "eg test1 198.202.138.72 5 0 10\n");
*** return 1;
* }
* char *ip_adrs = argv[1];
* unsigned short unit = atoi(argv[2]);
* unsigned short reg_no = atoi(argv[3]);
* unsigned short num_regs = atoi(argv[4]);
* printf("ip_adrs = %s unit = %d reg_no = %d num_regs = %d\n",
* ip_adrs, unit, reg_no, num_regs);
* // initialize WinSock
* static WSADATA wd;
* if (WSAStartup(0x0101, &wd))
* {
*** printf("cannot initialize WinSock\n");
*** return 1;
* }
* // set up socket
* SOCKET s;
* s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
* struct sockaddr_in server;
* server.sin_family = AF_INET;
* server.sin_port = htons(502); // ASA standard port
* server.sin_addr.s_addr = inet_addr(ip_adrs);
* int i;
* i = connect(s, (sockaddr *)&server, sizeof(sockaddr_in));
* if (i<0)
* {
*** printf("connect - error %d\n",WSAGetLastError());
*** closesocket(s);
*** WSACleanup();
*** return 1;
* }
* fd_set fds;
* FD_ZERO(&fds);
* timeval tv;
* tv.tv_sec = 5;
* tv.tv_usec = 0;
* // wait for permission to send
* FD_SET(s, &fds);
* i = select(32, NULL, &fds, NULL, &tv); // write
* if (i<=0)
* {
*** printf("select - error %d\n",WSAGetLastError());
*** closesocket(s);
*** WSACleanup();
*** return 1;
* }
* // build request of form 0 0 0 0 0 6 ui 3 rr rr nn nn
* unsigned char obuf[261];
* unsigned char ibuf[261];
* for (i=0;i<5;i++) obuf[i] = 0;
* obuf[5] = 6;
* obuf[6] = unit;
* obuf[7] = 3;
* obuf[8] = reg_no >> 8;
* obuf[9] = reg_no & 0xff;
* obuf[10] = num_regs >> 8;
* obuf[11] = num_regs & 0xff;
* // send request
* i = send(s, obuf, 12, 0);
* if (i<12)
* {
*** printf("failed to send all 12 chars\n");
* }
* // wait for response
* FD_SET(s, &fds);
* i = select(32, &fds, NULL, NULL, &tv); //read
* if (i<=0)
* {
*** printf("no TCP response received\n");
*** closesocket(s);
*** WSACleanup();
*** return 1;
* }
* // read response
* i = recv(s, ibuf, 261, 0);
* if (i<9)
* {
*** if (i==0)
*** {
***** printf("unexpected close of connection at remote end\n");
*** }
*** else
*** {
***** printf("response was too short - %d chars\n", i);
*** }
* }
* else if (ibuf[7] & 0x80)
* {
*** printf("MODBUS exception response - type %d\n", ibuf[8]);
* }
* else if (i != (9+2*num_regs))
* {
*** printf("incorrect response size is %d expected %d\n",i,(9+2*num_regs));
* }
* else
* {
*** for (i=0;i<num_regs;i++)
*** {
***** unsigned short w = (ibuf[9+i+i]<<8) + ibuf[10+i+i];
***** printf("word %d = %d\n", i, w);
*** }
* }
* // close down
* closesocket(s);
* WSACleanup();
* return 0;
}
Kris
Software Engineer
Phoenix,AZ
Basically you just send a command out on the TCP/IP connection in a certain format.
I have a C++ example and an OCX written by someone else that can do this. I don't know that
much about C++ but it is pretty simple to do. You build a command string and send it out and wait for a response. The C++ and OCX work fine.
I have a packet sniffer and looked at the data inside the packet and it is formated correctly (Using the C++ OCX).
when I try to send the command string in the same format the winsock control formats it to hex and then the command is wrong. If I sniff the packet
from my class the data is not correct. Is there a way to stuff the command string right into the
TCP/IP packet without it reformatting the data?
the command looks like this "00000000000601040000000A" it is in hex. It should look like this in the packet:
"00 00 00 00 00 06 01 04 00 00 00 0A"
But when I send the command it puts it into the packet like this:
"30 30 30 30 30 30 30 30 30 30 30 36 30 31 30 34 30 30 30 30 30 30 30 41"
I cannot figure out how to do this. If anyone has any Ideas or knows something about Socket Programming
I would appreciate some help. I am a VB programmer that does not know much about C++ and how it passes data to a TCP socket. I have
included here the C++ sample I found if anyone can tell me how to do the same in VB it would be a life saver.
Thanks for any help you can provide!!!!!!!
Here's the C++ code Sample. I have the whole OCX project in C++ too if it would help.
// test1.cpp - Win32 console app to read registers
// ============================================================
// test1.cpp 5/23/97
// example Win32 C++ program to read registers from PLC via gateway
// compile with BC45 or BC50
// default settings for Win32 console app
// empty DEF file
#include <winsock.h>
#include <stdio.h>
#include <conio.h>
int main(int argc, char **argv)
{
if (argc<5)
* {
*** printf("usage: test1 ip_adrs unit reg_no num_regs\n"
*** "eg test1 198.202.138.72 5 0 10\n");
*** return 1;
* }
* char *ip_adrs = argv[1];
* unsigned short unit = atoi(argv[2]);
* unsigned short reg_no = atoi(argv[3]);
* unsigned short num_regs = atoi(argv[4]);
* printf("ip_adrs = %s unit = %d reg_no = %d num_regs = %d\n",
* ip_adrs, unit, reg_no, num_regs);
* // initialize WinSock
* static WSADATA wd;
* if (WSAStartup(0x0101, &wd))
* {
*** printf("cannot initialize WinSock\n");
*** return 1;
* }
* // set up socket
* SOCKET s;
* s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
* struct sockaddr_in server;
* server.sin_family = AF_INET;
* server.sin_port = htons(502); // ASA standard port
* server.sin_addr.s_addr = inet_addr(ip_adrs);
* int i;
* i = connect(s, (sockaddr *)&server, sizeof(sockaddr_in));
* if (i<0)
* {
*** printf("connect - error %d\n",WSAGetLastError());
*** closesocket(s);
*** WSACleanup();
*** return 1;
* }
* fd_set fds;
* FD_ZERO(&fds);
* timeval tv;
* tv.tv_sec = 5;
* tv.tv_usec = 0;
* // wait for permission to send
* FD_SET(s, &fds);
* i = select(32, NULL, &fds, NULL, &tv); // write
* if (i<=0)
* {
*** printf("select - error %d\n",WSAGetLastError());
*** closesocket(s);
*** WSACleanup();
*** return 1;
* }
* // build request of form 0 0 0 0 0 6 ui 3 rr rr nn nn
* unsigned char obuf[261];
* unsigned char ibuf[261];
* for (i=0;i<5;i++) obuf[i] = 0;
* obuf[5] = 6;
* obuf[6] = unit;
* obuf[7] = 3;
* obuf[8] = reg_no >> 8;
* obuf[9] = reg_no & 0xff;
* obuf[10] = num_regs >> 8;
* obuf[11] = num_regs & 0xff;
* // send request
* i = send(s, obuf, 12, 0);
* if (i<12)
* {
*** printf("failed to send all 12 chars\n");
* }
* // wait for response
* FD_SET(s, &fds);
* i = select(32, &fds, NULL, NULL, &tv); //read
* if (i<=0)
* {
*** printf("no TCP response received\n");
*** closesocket(s);
*** WSACleanup();
*** return 1;
* }
* // read response
* i = recv(s, ibuf, 261, 0);
* if (i<9)
* {
*** if (i==0)
*** {
***** printf("unexpected close of connection at remote end\n");
*** }
*** else
*** {
***** printf("response was too short - %d chars\n", i);
*** }
* }
* else if (ibuf[7] & 0x80)
* {
*** printf("MODBUS exception response - type %d\n", ibuf[8]);
* }
* else if (i != (9+2*num_regs))
* {
*** printf("incorrect response size is %d expected %d\n",i,(9+2*num_regs));
* }
* else
* {
*** for (i=0;i<num_regs;i++)
*** {
***** unsigned short w = (ibuf[9+i+i]<<8) + ibuf[10+i+i];
***** printf("word %d = %d\n", i, w);
*** }
* }
* // close down
* closesocket(s);
* WSACleanup();
* return 0;
}
Kris
Software Engineer
Phoenix,AZ