I am trying to send struct over sockets. The connection works fine with arrays,
but with a simple struct the server recieves only
Recv - 1 - 1
If i change the ID or status to another number(while the client is running), it recieves nothing, but the client has sended. And if i change it back to ID=1 and status=1 it send it again and recieve it correctly.
Client-Side:
void func()
{
printf("Send - %i - %i\n", mRELAIS.ID, mRELAIS.status);
send(sockfd,&mRELAIS,sizeof(struct RELAIS),0);
}
Output: Send - 1 - 1 respectively Send - 1 - 0
Where i change it on the Client-Side:
if(temperature>(g_Value+g_PlusMinus) && relais[0]==0)
{
printf("%.1lf°C Relais wird 1 Soll %.1lf\n", temperature,(g_Value+g_PlusMinus));
mRELAIS.ID=1;
mRELAIS.status=1;
func();
}
else if(temperature<(g_Value-g_PlusMinus) && relais[0]==1)
{
printf("%.1lf°C Relais wird 0 Soll %.1lf\n", temperature,(g_Value-g_PlusMinus));
mRELAIS.ID=1;
mRELAIS.status=0;
func();
}
Server-Side:
for (;;)
{
recv(connfd, &mRELAIS, sizeof(struct RELAIS),0);
printf("Recv - %i - %i\n", mRELAIS.ID, mRELAIS.status);
....
}
Output: Send - 1 - 1 respectively
Does anyone have a suggestion to solve the problem?
Thanks.
Not sure if this is your immediate problem but your receive code is wrong. Tco is a steaming protocol, not a message oriented one. You might receive a 50 byte send as 50 one byte receives. Or 2 25 bytes receives. You must lipp on recv till you have the entire send. There s in turn means that the receiver has to know the message size somehow
Related
I'm creating a mini web server in C.
The following function is supposed to read in data from the client computer.
The objective is to read the second piece of data after the first space. Each piece of incoming data is space separated.
For example, if the incoming data is:
GET /123/456
then I'd expect /123/456.
If the incoming data is:
GET /123/456 789
then I'd still expect /123/456.
This relevant fragment is from an external function that sets up a 10 KB buffer and calls the problematic function:
//nsock is a valid socket handle from an accept() call.
printf("CLIENT CONNECTION!\n");
char req[10000];long reqsz=10000;
getreq(req,&reqsz,nsock);
printf("Received %d bytes\n",reqsz);
printf("Data: %s\n",req);
"CLIENT CONNECTION!" appears on the screen, but "Received" does not appear if bufsize inside the function is a high value. If I set it to a low value like 16, or 100, then everything is displayed correctly. Why do large numbers like 5000 not work?
This is the problematic function:
//getreq params in: req=external buffer for data
// reqsz=size of external buffer. I set 10000
// nsock=valid socket pointer from accept()
//
//getreq params out: reqsz=actual size of data returned
// req=actual data
//
void getreq(char* req,unsigned long *reqsz,long nsock){
//bufsize=how many bytes to read at once. High values like 5000 cause a stall.
//buffer=buffer of data from recv call
const unsigned long ibs=*reqsz,bufsize=5000;
char buffer[ibs],*rp=req;
//spacect=# of spaces in data read
//szct=iterator variable
//mysz=total length of returned data
//bufct=buffer counter to prevent segfault
//recvsz=data size returned from recv or
// forced -2 if buffer hits capacity
// or 2nd space in returned data is found
unsigned long spacect=0,szct=0,mysz=0,bufct=0;
long recvsz=1;char *p=buffer;
//
//Expected data: GET /whatever HTTP/x.x but we
// want /whatever
//
//loop until 2nd space is found or
//ibs bytes of data have been processed
while (recvsz > 0 && bufct < ibs){
recvsz=recv(nsock, p, bufsize, 0);
if (recvsz < 1){break;}
for (szct=1;szct<=recvsz;szct++){
if (*p==' '){spacect++;if (spacect > 2){spacect=2;recvsz=-2;break;}}
if (spacect==1 && *p != ' '){mysz++;if (mysz <= *reqsz){*rp++=*p;}}
p++;bufct++;if (bufct > ibs){recvsz=-2;break;}
}
}
// Process rest of data to try to avoid client errors
while (recvsz == -2){
recvsz=recv(nsock, buffer, bufsize, 0);
}
*reqsz=mysz;
}
I'm trying to send through radio apc220 from a C-xenomai program to and from an arduino Mega.
I have one task created for sending, and one for reading in the xenomai program.
The arduino side reads and the writes to serial.
The baud-rates are both equal and tried 9600 and 19200, but the data recieved is random data, and not the values sent.
C code (This is in a task with "rt_task_set_periodic(NULL, TM_NOW, TM_INFINITE);" and priority in task creation of 99). Values of bufferMotorX are constantly changing.
strcpy(buffer,bufferMotor1);
strcat(buffer,bufferMotor2);
strcat(buffer,bufferMotor3);
strcat(buffer,bufferMotor4);
fprintf(stderr,"sending...%s\n",buffer);
write(apcFd, buffer, CONTROLLER_BUFFER_SIZE);
Arduino side:
if (Serial.available() > 0) {
// read the incoming byte:
for (int i=0; i < 12; i++)
{
inputByte=Serial.read();
inputBuffer[i]=inputByte;
}
bufferMotor1[0]=inputBuffer[0];
bufferMotor1[1]=inputBuffer[1];
bufferMotor1[2]=inputBuffer[2];
/*bufferMotor2[0]=inputBuffer[3];
bufferMotor2[1]=inputBuffer[4];
bufferMotor2[2]=inputBuffer[5];
bufferMotor3[0]=inputBuffer[6];
bufferMotor3[1]=inputBuffer[7];
bufferMotor3[2]=inputBuffer[8];
bufferMotor4[0]=inputBuffer[9];
bufferMotor4[1]=inputBuffer[10];
bufferMotor4[2]=inputBuffer[11];*/
Serial.print("I received: ");
Serial.println(bufferMotor1);
motor1=atoi(bufferMotor1);
Any ideas on what I'm doing wrong?
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'm trying to figure out why netstat on my Mac OS X computer prints stuff like "got 4 twice".
For example:
$ netstat | head -15
Active Internet connections
Proto Recv-Q Send-Q Local Address Foreign Address (state)
[...]
tcp4 0 0 localhost.56892 localhost.26164 ESTABLISHED
got 4 twice
got 16 twice
got 1 twice
got 4 twice
got 4 twice
got 8 twice
The message is printed by netstat's inet.c, in the function protopr which basically does the following:
Calls sysctlbyname(3) using e.g. net.inet.tcp.pcblist_n to get a list of PCBs (I guess?)
Loops through the results, collecting pointers to various structs, whose type is called an xgn_kind
It sets a bit for each xgn_kind it has seen. If it sees any of them twice, it complains with the message "got %d twice".
I've cut out the relevant parts of the code:
void
protopr(uint32_t proto, /* for sysctl version we pass proto # */
char *name, int af)
{
/* ... */
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
if (errno != ENOENT)
warn("sysctl: %s", mibvar);
return;
}
/* ... */
for (next = buf + ROUNDUP64(xig->xig_len);
next < buf + len;
next += ROUNDUP64(xgn->xgn_len))
{
/* ... */
if ((which & xgn->xgn_kind) == 0) {
which |= xgn->xgn_kind;
/* ... */
} else {
printf("got %d twice\n", xgn->xgn_kind);
}
/* ... */
}
My question is, finally:
Why is this happening? Is it faulty data coming back from sysctl? Is the loop above incorrect, i.e., can sysctl actually return several structs per kind?
Note that I'm running Mac OS X -- and the code is indeed a little bit different from FreeBSD's.