Linux Tool to Send Raw Data to a Tcp Server

Linux tool to send raw data to a TCP server

netcat or telnet, i have used both in the past to test simple text based protocols. netcat is more flexible.

Linux command to send data to a remote tcp-client

Install netcat

yum install nc

Make it to listen to a particular port number

nc –l portnumber &

Lets validate it using netstat from a different console:

netstat -anlp |grep yourportnumber

PS: Change the installation command based on your linux flavor.

Linux TCP server, sending RAW data to few clients every X seconds

You may want to check out D.J. Bernstein's tcpserver (see http://cr.yp.to/ucspi-tcp/tcpserver.html). Basically, you can simply run your C program under tcpserver, and tcpserver will handle everything as far as setting up the sockets, listing for incoming connections on whatever port you are using, etc. When an incoming connection arrives on the port that you specify, tcpserver will spawn an instance of your program and pipe incoming info from the client to your program's STDIN, and pipe outgoing info from your program's STDOUT back to the client. This way, you can concentrate on your program's core logic (and simply read/write to stdout/stdin), and let tcpserver handle all of the heavy lifting as far as the sockets, etc.

How to read all of STDOUT produced by system() call into a socket written in C?

The way your code is sending and reading strings is not sufficient.

TCP is a byte stream. There is no 1-to-1 relationship between sends and reads. As such, the sender MUST either:

  1. send the string length before sending the string's data.
  2. send a unique terminator after the string data.

And the receiver MUST either:

  1. read the length then read the specified amount of data.
  2. read until the terminator is reached.

Also, send()/write() and recv()/read() can return fewer bytes than requested, so they need to be called in loops (or, in the case of recv(), you can use the MSG_WAITALL flag).

Try something more like this instead:

// common functions ...

bool sendRaw(int sock, void *data, size_t len)
{
char *ptr = (char*) data;
while (len > 0) {
int sent = send(sock, ptr, len, MSG_NOSIGNAL);
if (sent < 0) return false;
ptr += sent;
len -= sent;
}
return true;
}

int recvRaw(int sock, void *data, size_t len)
{
char *ptr = (char*) data;
while (len > 0) {
int recvd = recv(sock, ptr, len, MSG_NOSIGNAL);
if (recvd <= 0) return recvd;
ptr += recvd;
len -= recvd;
}
return 1;
}

bool sendUInt32(int sock, uint32_t value)
{
value = htonl(value);
return sendRaw(sock, &value, sizeof(value));
}

uint32_t recvUInt32(int sock)
{
uint32_t value;
if (recvRaw(sock, &value, sizeof(value)) <= 0) return -1;
return ntohl(value);
}

bool sendString(int sock, const char *str)
{
uint32_t len = strlen(str);
if (!sendUInt32(sock, len)) return false;
return sendRaw(sock, str, len);

/* alternatively:
return sendRaw(sock, str, strlen(len) + 1);
*/
}

/*
bool grow(char **str, size_t *cap, size_t stepBy)
{
size_t newcap = cap + stepBy;
char *newstr = (char*) realloc(*str, newcap);
if (!newstr) return false;
*str = newstr;
*cap = newcap;
return true;
}
*/

char* recvString(int sock)
{
uint32_t len = recvUInt32(sock);
if (len == -1) return NULL;

char *str = (char*) malloc(len+1);
if (!str) return NULL;

if (recvRaw(sock, str, len) <= 0){
free(str);
return NULL;
}

str[len] = '\0';
return str;

/* alternatively:

char ch, *str = NULL;
size_t len = 0, cap = 0;

do{
if (recvRaw(sock, &ch, 1) <= 0){
free(str);
return NULL;
}

if (ch == '\0') break;

if (len == cap){
if (!grow(&str, &cap, 256)){
free(str);
return NULL;
}
}

str[len++] = ch;
}
while (1);

if (len == cap){
if (!grow(&str, &cap, 1)){
free(str);
return NULL;
}
}

str[len] = '\0';
return str;
*/
}
// server ...

char *command;

while ((command = recvString(sock)) != NULL){
// ...
system(command);
free(command);

// read from command's stdout until finished ...

if (!sendString(sock, output, outputLength)) break;
}
// client ...

if (sendString(sock, command)){
char *output = recvString(sock);
if (output){
//print the output somewhere
free(output);
}
}

Alternatively, if you don't know the length of the command's response ahead of time, and/or don't want to buffer it all in a single memory buffer, then you can read it in chunks, sending each chunk as you go, eg:

// common functions, see above ...

typedef struct _chunk
{
uint8_t size;
char data[256];
} chunk;

bool sendChunk(int sock, const chunk *chk)
{
uint8_t size = chk ? chk->size : 0;
if (!sendRaw(sock, &size, 1)) return false;
if (chk) return sendRaw(sock, chk->data, size);
return true;
}

bool recvChunk(int sock, chunk *chk)
{
if (recvRaw(sock, &(chk->size), 1) <= 0) return false;
if (chk->size) return recvRaw(sock, chk->data, chk->size);
return true;
}
// server ...

bool sendOutput(int sock)
{
chunk chk;
int size;

do{
// read from command's stdout ...
size = read(..., chk.data, sizeof(chk.data));
if (size <= 0) break;

chk.size = (uint8_t) size;
if (!sendChunk(sock, &chk)) return false;
}
while(1);

// tell client the data is finished ...
return sendChunk(sock, NULL);
}

char *command;

while ((command = recvString(sock)) != NULL){
// ...
system(command);
free(command);
if (!sendOutput(sock)) break;
}
// client ...

if (sendString(sock, command)){
chunk chk;
do{
if (!recvChunk(sock, &chk)) break;
if (chk.size == 0) break;
//print the chk.data somewhere
}
while (1);
}

Have PLC Controller Listen/Send Custom TCP Packets?

It sounds a bit like reinventing the wheel. You want to make something like KepServerEX?

http://www.kepware.com/kepserverex/

There are also two things to consider - one is the ability to interface with the PLC to share data (ie: for a custom HMI) and the other is to program the PLC. For the latter you still need the control software from the manufacturer unless you're willing to reverse engineer and re-write it from the ground up.

Keep in mind, also, that PLCs don't work the same way that other software does. There are no functions or procedures or classes or objects or even really any "commands", per se. A PLC is a system which executes a continuous fixed program of mostly raw logic rules and calculations. A typical interface to an HMI involves reading and writing directly to/from logic bits and word data (ie:hardware memory locations) which represent the current state of the machine. OPC already does this just fine so I'm not quite sure what you're going for.

If you're looking for a cheap/free alternative to a full commercial package, something here may work for you :

http://www.opcconnect.com/freesrv.php



Related Topics



Leave a reply



Submit