I am trying a C program for communication between client and server. I want my server to randomly generate an array, send it to the client and get back the sorted array from client to server. But, when I print the array sent by the server, the client shows only zeros. I guess there is problem either send function in server or receive/read function in client. Here is my code:
Server Side:
1- to create a random array
//int ip[255];
void GenIpArray()//generate random values and store in ip[]
{
for(int i=0;i<255;i++)
{
ip[i]= rand()%100 + 100;
}
}
2- to send array to the client
void write(LPVOID sock_fd)//int sock_fd=socket(AF_INET,SOCK_STREAM,0);
{
while(1)
{
send((int)sock_fd,(char*)&ip,255,0);
//let int ip[255] = {123, 109, 240, 150};
}
}
Client Side:
1- to receive from server
void read(LPVOID sock_fd)
{
while(1)
{
if(recv((unsigned int)sock_fd,(char*)&arr,255,0)>0)
{
printf("recevied: ");
strcpy((char*)x, (char*)arr);
printf("%c",(char *)&x);//this statement prints #
printArray();//function to print array
break;
}
}
}
2- function to print the array
void printArray()
{
printf("\n\n Printing the array:\n");
for(int k=0;k<255;k++)
printf("\n %d",x[k]);
}
Firstly, you need to send the correct size:
send((int)sock_fd, (char *)ip, 255 * sizeof(int), 0);
Then, you need to recv the correct size, reading it straight into x:
size_t bytes_received = recv((int)sock_fd, (char *)x, 255 * sizeof(int), 0);
Now x contains bytes_received / sizeof(int) numbers:
size_t ints_received = bytes_received / sizeof(int);
So you can use this number to loop and print them:
for (unsigned int k = 0; k < ints_received; k++) {
printf("%d\n", x[k]);
}
For portability, you should really be converting your ints to network byte order with htons before sending them, and then converting them back to host byte order with ntohs after receiving them.
The error is simply the use of strcpy! It stops copying on first null, and you are sending ints between 100 and 200. So at best only first byte will end in x and all the other bytes will be what was there at the beginning (0 for static duration arrays).
Never, ever use strcpy for binary data, but only memcpy
And that's not all:
you should allways control the return values of send and receive.
printf("%c",(char *)&x); is non sense: you print the first byte of the address or x array
if ip and arr are real arrays (not pointers) use directly sizeof(ip) and sizeof(arr)
send((int)sock_fd,(char*)ip,sizeof(ip),0);
recv((unsigned int)sock_fd,(char*)arr,sizeof(arr),0)
Related
I'm new to Arduino and fairly new to programming. I'm trying to send an array of integers over UDP to MaxMSP. Using the .print method in the WiFiUDP library works for sending one integer per packet:
void loop() {
Udp.beginPacket(hostIP, HOST_PORT);
Udp.print("start");
for (int i = 0; i < NUMBER_OF_SENSORS; i++) {
int adcValue = analogRead(i);
Udp.print(adcValue);
}
Udp.endPacket();
Udp.flush();
}
The problem is that this is quite slow. I'm getting a refresh rate of about 10 ms for each sensor on the Max end, and I'm assuming that by writing all of the integers (only 4 at the moment) to a single buffer and sending it in its own packet, I'd be able to quadruple the speed. I've tried this:
void loop() {
byte sensorBuffer [NUMBER_OF_SENSORS * 2];
for (int i = 0; i < NUMBER_OF_SENSORS; i++) {
int adcValue = analogRead(i);
sensorBuffer[i*2] = highByte(adcValue);
sensorBuffer[i*2+1] = lowByte(adcValue);
}
Udp.beginPacket(hostIP, HOST_PORT);
Udp.write(sensorBuffer, NUMBER_OF_SENSORS * 2);
Udp.endPacket();
Udp.flush();
}
This produces garbage on the Max end. I have a vague idea why this is the case - the array is formatted as 7-bit ASCII values? - but I haven't been able to figure out how to get it to work. Any input is much appreciated.
I'm trying to send the data from two sensors through 433MHz radio communication. I have succeeded in sending and receiving the string(array of char) "number1,number2".
Now I'm trying to store both numbers in separate int variables (the values are over 256).
I've tried with almost everything (sscanf and atoi mainly), but it does not seem to work.
To A0 and A1 I have connected two potentiometers, whose values I want to store in valorX and valorY in the receiver arduino.
What do you suggest?
I cannot assure I used correctly sscanf and atoi.
Transmitter code:
#include <VirtualWire.h>
int xvalue;
int yvalue;
void setup() {
Serial.begin(9600);
vw_set_ptt_inverted(true); //
vw_set_tx_pin(12);
vw_setup(4000);// speed of data transfer Kbps
}
void loop() {
xvalue=analogRead(A0);
yvalue=analogRead(A1);
int envioX = map(xvalue, 0, 1023, 001, 1000); //I prefer to not send 0
int envioY = map(yvalue, 0, 1023, 001, 1000);
//Mando los datos del joystic
char envioXY[]="";
sprintf(envioXY,"%d,%d",envioX,envioY);
EnviarDatos(envioXY);
delay(1000);
}
void EnviarDatos(char datos[]){
vw_send((uint8_t *)datos, strlen(datos)); //vw_send(message, length)
vw_wait_tx(); // Wait until the whole message is gone
}
Receiver code:
#include <VirtualWire.h>
char recibo[8]="";
int valorX;
int valorY;
void setup(){
vw_set_ptt_inverted(true); // Required for DR3100
vw_set_rx_pin(12);
vw_setup(4000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
Serial.begin(9600);
Serial.println("setup");
}
void loop(){
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)){ //check to see if anything has been received
for(int i=0;i<buflen;i++){
recibo[i]=char(buf[i]);
Serial.print(recibo[i]);
}
recibo[buflen]=NULL;
//String str(recibo);
//What here to get both int??
}
}
What do you suggest?
I cannot assure I used correctly sscanf and atoi.
So the main question is how to convert "number1,number2" to int1=number1 and int2=number2.
Thanks and cheers
Gabriel
Transmitter code:
You must declare storage for the sprintf to use. You have only declared a 1-byte array which contains a NUL (0 byte) as the first and only element [0]:
char envioXY[]="";
Change it to this, which declares a character array with 24 elements:
char envioXY[ 24 ];
Although uninitialized, sprintf will set the array elements as it formats your 2 integers.
Receiver code:
After recibo[buflen] = NULL;, you can parse it with this:
sscanf( recibo, "%d,%d", &valorX, &valorY );
The format string matches the sprintf format, and the address of the two integers is passed in, not just the two integers.
I'm continuously sending 2D arrays of pixel values (uint32) from LabVIEW to a C-program through TCP/IP with the resolution 160x120. The purpose of the C-program is to display the received pixel values as 2D arrays in the console application. I'm sending the pixels as stream of bytes, and using the recv function in Ws2_32.lib to receive the bytes in the C-program. Then I'm converting the bytes to uint32 values and displaying them in the console application using a 2D arrays, so every 2D array will represent an image.
I have en issue with the frame rate though. I'm able to send 30 frames per second in LabVIEW, but when I open the TCP/IP connection with the C-program, the frame rate goes down to 1 frame per second. It must be an issue with the C-program, since I managed to send the desired frames per second with the same LabVIEW program to a corresponding C# program.
The C-code:
#define DEFAULT_BUFLEN 256
#define IMAGEX 120
#define IMAGEY 160
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
int iResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
typedef unsigned int uint32_t;
unsigned int x=0,y=0,i,n;
uint32_t image[IMAGEX][IMAGEY];
size_t len;
uint32_t* p;
p = (uint32_t*)recvbuf;
do
{
iResult = recv(new_socket, recvbuf, recvbuflen, 0);
len = iResult/sizeof(uint32_t);
for(i=0; i < len; i++)
{
image[x][y] = p[i];
x++;
if (x >= IMAGEX)
{
x=0;
y++;
}
if (y >= IMAGEY)
{
y = 0;
x = 0;
//print image
for (n=0; n< IMAGEX*IMAGEY; n++)
{
printf("%d",image[n%IMAGEX][n/IMAGEY]);
if (n % IMAGEX)
{
printf(" ");
}
else
{
printf("\n");
}
}
}
}
} while ( iResult > 0 );
try reducing the prints .. Since you are reading and printing in the same thread, the data in the TCP connection will fill up and it will then back pressure the other end (LABView) and the LABView will stop sending data until it gets the green signal from the other end (you C program)
To start with you can debug by replacing this
for (n=0; n< IMAGEX*IMAGEY; n++)
{
printf("%d",image[n%IMAGEX][n/IMAGEY]);
if (n % IMAGEX)
{
printf(" ");
}
else
{
printf("\n");
}
}
with
printf("One frame recv\n");
and see if it makes any difference. I am assuming your tcp connection has ample bandwidth
Very hard to diagnose without further information. I can give a few suggestions, however.
First of all, your recv call is using a small buffer, so you are spending a lot of time calling it. Why not read a whole frame at a time? Also, you read in the data and then copy it to the image array. Wouldn't it be simpler to just use the image array itself? Combining those two suggestions would have recv reading a full frame directly into the image array, saving a lot of time.
Another source of the problem could be the console. With the sample code you provided, you are attempting to write 30*120*160=57,600 integer values per second to the terminal. If the average value, with delimiter, takes up 8 characters, that's 4 million characters per second. It's entirely possible that the display just can't go that fast, in which case things would back up and slow down all the way to the server writing to the socket.
There are several ways to handle this, but it's too much to go into here.
I just want to send an array adc_array=[w, x, y, z] from client to server. Below is the client side code whereas my server is in python which accepts json only. I get no error when i compile the code however get 2 warnings :
1- warning: pointer targets in passing argument 2 of 'UDPWrite' differ in signedness.
2- warning: no newline at end of file.
But at the server side, i am not able to receive the whole array, instead i just get the first character of the array i.e. [ .
I am new to C programming. I would really appreciate any help.
// Main function
void FlyportTask()
{
// Flyport connects to default network
WFConnect(WF_DEFAULT);
while(WFGetStat() != CONNECTED);
vTaskDelay(25);
UARTWrite(1,"Flyport Wi-fi connected...hello world!\r\n");
BOOL UdpSocketOpenRequest=TRUE;
BYTE UdpSocket=0;
// openinging UDP socket
if (UdpSocketOpenRequest) //open socket
{
UdpSocketOpenRequest=FALSE;
if (UdpSocket!=0) //if this is not equals to zero
{
UDPClientClose(UdpSocket);
}
UARTWrite(1,"OpenSocket\r\n");
UdpSocket= UDPClientOpen("10.0.0.106", "8000"); //Client socket opening
}
while(1)
{
//defining pointer
int *array_pointer;
int adc_array[4];
int j;
char buf[10]; //buffer to print
// I have made a separate function to get adc values which returns the pointer to the array.
array_pointer = get_adcval();
UARTWrite (1, "ADC Array\r\n");
for (j = 0; j < 4; j++)
{
adc_array[j] = *(array_pointer + j);
sprintf (buf, "%d", adc_array[j]);
UARTWrite (1, buf);
UARTWrite (1, "\n");
}
//if UDP socket is open, send the data
if ((UdpSocket!=0))
{
// defining pointer of serial_out
char *s_out;
int size;
// creating a JSON array from adc_array with 4 elements
cJSON * int_array = cJSON_CreateIntArray(adc_array,4);
// Serializing the array
s_out = cJSON_Print(int_array);
//Writing to the serial output/monitor
UARTWrite(1, "\r\narray to be sent\r\n");
UARTWrite(1, s_out);
UARTWrite(1,"\r\n");
// Assume adc_array=[1021, 1022, 1023, 1024]
// I get output [1021, 1022, 1023, 1024]
//compose message
size = strlen(s_out);
UDPWrite (UdpSocket, s_out, size);
// at the server side, i just receive only first character i.e. [
/*to free the memory */
free(s_out);
}
//
// remember to add delay vTaskDelay(50) 50ms
//remember to close the socket
}
}
You didn't allocated memory for s_out. even if it is printing correct result on UART but still it can be overwritten by any of the UARTWrite functions or strlen() function in the next lines. If it is overwritten then the "size" variable will get the number of bytes starting from the first byte to first null character in the memory (this is how strlen() functions). hence the "size" value can be totally random. it can be 0 or 1 or 1000. if the size is not correct then you will receive only "size" number of bytes. In your case it is possible that size is one. try printing size before UDPWrite. fix this problem by adding a malloc call before serializing the array.
If it doesn't work either then check your receiver side. is your receiver working fine if you send some dummy data from a tested python client (or any other tested or reliable client)? if no then there is some problem with your receiver.
Print out what strlen(s_out) returns, also print out the return value of UDPWrite ( I assume that like any write function this will be returning the size of the data which is written to the socket).
By reading the function names I presume you are using UDP transmission which is unreliable.
I am trying to send data between a client/Server, the data looks like
typedef Struct Message
{ int id;
int message_length;
char* message_str;
}message;
I am trying to Write and Read this message between a client and server constantly updating the elements in this struct. I have heard Writev may do the trick. i want to send a
message to the server and then the server pulls out the elements and uses those elements as conditionals to execute the proper method?
Assuming you want to do the serialization yourself and not use Google Protocol Buffers or some library to handle it for you, I'd suggest writing a pair of functions like this:
// Serializes (msg) into a flat array of bytes, and returns the number of bytes written
// Note that (outBuf) must be big enough to hold any Message you might have, or there will
// be a buffer overrun! Modifying this function to check for that problem and
// error out instead is left as an exercise for the reader.
int SerializeMessage(const struct Message & msg, char * outBuf)
{
char * outPtr = outBuf;
int32_t sendID = htonl(msg.id); // htonl will make sure it gets sent in big-endian form
memcpy(outPtr, &sendID, sizeof(sendID));
outPtr += sizeof(sendID);
int32_t sendLen = htonl(msg.message_length);
memcpy(outPtr, &sendLen, sizeof(sendLen));
outPtr += sizeof(sendLen);
memcpy(outPtr, msg.message_str, msg.message_length); // I'm assuming message_length=strlen(message_str)+1 here
outPtr += msg.message_length;
return (outPtr-outBuf);
}
// Deserializes a flat array of bytes back into a Message object. Returns 0 on success, or -1 on failure.
int DeserializeMessage(const char * inBuf, int numBytes, struct Message & msg)
{
const char * inPtr = inBuf;
if (numBytes < sizeof(int32_t)) return -1; // buffer was too short!
int32_t recvID = ntohl(*((int32_t *)inPtr));
inPtr += sizeof(int32_t);
numBytes -= sizeof(int32_t);
msg.id = recvID;
if (numBytes < sizeof(int32_t)) return -1; // buffer was too short!
int32_t recvLen = ntohl(*((int32_t *)inPtr));
inPtr += sizeof(int32_t);
numBytes -= sizeof(int32_t);
msg.message_length = recvLen; if (msg.message_length > 1024) return -1; /* Sanity check, just in case something got munged we don't want to allocate a giant array */
msg.message_str = new char[msg.message_length];
memcpy(msg.message_str, inPtr, numBytes);
return 0;
}
With these functions, you are now able to convert a Message into a simple char-array and back at will. So now all you have to do is send the char-array over the TCP connection, receive it at the far end, and then Deserialize the array back into a Message struct there.
One wrinkle with this is that your char arrays will be variable-length (due to the presence of a string which can be different lengths), so your receiver will need some easy way to know how many bytes to receive before calling DeserializeMessage() on the array.
An easy way to handle that is to always send a 4-byte integer first, before sending the char-array. The 4-byte integer should always be the size of the upcoming array, in bytes. (Be sure to convert the integer to big-endian first, via htonl(), before sending it, and convert it back to native-endian on the receiver via htonl() before using it).
Okay, I'll take a stab at this. I'm going to assume that you have a "message" object on the sending side and what you want to do is somehow send it across to another machine and reconstruct the data there so you can do some computation on it. The part that you may not be clear on is how to encode the data for communications and then decode it on the receiving side to recover the information. The simplistic approach of just writing the bytes contained in a "message" object (i.e. write(fd, msg, sizeof(*msg), where "msg" is a pointer to an object of type "message") won't work because you will end up sending the value of a virtual address in the memory of one machine to different machine and there's not much you can do with that on the receiving end. So the problem is to design a way to pass an two integers and a character string bundled up in a way that you can fish them back out on the other end. There are, of course, many ways to do this. Does this describe what you are trying to do?
You can send structs over socket, but you have to serialize them before sending the struct using boost serialization.
Here is a sample code :
#include<iostream>
#include<unistd.h>
#include<cstring>
#include <sstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
using namespace std;
typedef struct {
public:
int id;
int message_length;
string message_str;
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &ar, const unsigned int vern)
{
ar & id;
ar & message_length;
ar & message_str;
}
} Message;
int main()
{
Message newMsg;
newMsg.id = 7;
newMsg.message_length = 14;
newMsg.message_str="Hi ya Whats up";
std::stringstream strData;
boost::archive::text_oarchive oa(strData);
oa << newMsg;
char *serObj = (char*) strData.str().c_str();
cout << "Serialized Data ::: " << serObj << "Len ::: " << strlen(serObj) << "\n";
/* Send serObj thru Sockets */
/* recv serObj from socket & deserialize it */
std::stringstream rcvdObj(serObj);
Message deserObj;
boost::archive::text_iarchive ia(rcvdObj);
ia >> deserObj;
cout<<"id ::: "<<deserObj.id<<"\n";
cout<<"len ::: "<<deserObj.message_length<<"\n";
cout<<"str ::: "<<deserObj.message_str<<"\n";
}
you can compile the program by
g++ -o serial boost.cpp /usr/local/lib/libboost_serialization.a
you must have libboost_serialization.a statically compiled in your machine.
Keeping the sockets 'blocking' will be good and you have to devise for reading these structs from recv buffer.