Search code examples
arrayscsocketsbooleanudp

Bool array transfer from client with UDP in C


I need to create a simple modbus application that will transfer data in bool type. I created client and server codes for this. Client side:

int Client(bool message[8])
{
struct sockaddr_in si_other;
int s, slen=sizeof(si_other);
bool buf[BUFLEN];
WSADATA wsa;

if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
    exit(EXIT_FAILURE);
    return 1;
}

if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
    exit(EXIT_FAILURE);
    return 2;
}

memset((bool *) &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);


if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
    exit(EXIT_FAILURE);
    return 3;
}

//  closesocket(s);
//  WSACleanup();

return 0;
}

Server side:

int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
bool buf[BUFLEN];
WSADATA wsa;

slen = sizeof(si_other) ;

printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
    printf("Failed. Error Code : %d",WSAGetLastError());
    exit(EXIT_FAILURE);
}
printf("Initialised.\n");

if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
    printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");

server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( PORT );

if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
    printf("Bind failed with error code : %d" , WSAGetLastError());
    exit(EXIT_FAILURE);
}
puts("Bind done");

while(1)
{
    printf("Waiting for data...\n");
    fflush(stdout);

    memset(buf,'0', BUFLEN);

    if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
    {
        printf("recvfrom() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));

    for (int i=0; i<=7; i++) {
        printf("%d", buf[i]);
    }

    printf("Data: %d\n" , buf);
    printf("%s-%s-%s\n",buf[0],buf[1],buf[2]);     //When I run this code, it works just like the code with 'for' and gives an error.

    if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
    {
        printf("sendto() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }
}

closesocket(s);
WSACleanup();

return 0;
}

When I run the application, the data transfer is not correct. For example, when I send data as '101010', it transmits '100000'; If send data as '110101', it transmits '110000' or if send it as '011111', it transmits '000000'. In other words, in order to read a data with a value of '1' correctly, all the values before that data must be '1'.

When I remove the 'for' part in the code and try to read the whole buf directly ( printf("Data: %d\n" , buf) ) , it reads '6421972' data. Even if I change the data, this number does not change. What can I do to overcome this problem?


Solution

  • In your client, strlen(message) will count chars until the first '0'encoutered. So your sent bool array never will be of length 8.

    Your client must then take the buffer length too in parameter to fix this.

    If your buffer is a true C array (not an allocated pointer) then sizeof statement can give the length. But if you use a malloc'd pointer for buf, sizeof statement will always return 8, never less, never more (in 64 bit systems), that is the size of a pointer only.

    In short, always keep a length integer alongside with a buffer.