DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

TCP/IP Communication from PC to RaspberryPi

Thu Dec 20, 2018 2:47 pm

I know there are a tons of threads on TCP/IP and Socket programming. I just wonder, why my code will not work on the PI. It works when I run it locally, no problem so far.
But when I try to run my server-code on the PI, there seems to be no connection happening.

I am using c for this and here is my code so far (basically mostly from a tutorial)
What I try to achieve is, to read a JSON as client and send the data to the PI which will further process it.

Server (intended to run on the pi)

Code: Select all

int main(){
    int welcomeSocket, newSocket;
    char buffer[10000];
    struct sockaddr_in serverAddr;
    struct sockaddr_storage serverStorage;
    socklen_t addr_size;

    /*---- Create the socket. The three arguments are: ----*/
    /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
    welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (welcomeSocket == -1)    {
        printf("Could not create socket");
    }

    /*---- Configure settings of the server address struct ----*/
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(7891);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    /* Set all bits of the padding field to 0 */
    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

    /*---- Bind the address struct to the socket ----*/
    bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

    /*---- Listen on the socket, with 5 max connection requests queued ----*/
    if(listen(welcomeSocket,5)==0)
        printf("Listening\n");
    else
        printf("Error\n");

    /*---- Accept call creates a new socket for the incoming connection ----*/
    addr_size = sizeof serverStorage;
    newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);



    /*---- Read the message from the server into the buffer ----*/
    recv(newSocket, buffer, 10000, 0);

    /*---- Print the received message ----*/
    printf("Data received: %s",buffer);

    return 0;
}
Client (intended to run on my Windows-PC, later needs to be adapted for android)

Code: Select all

void readfile(char* filepath, char* fileContent)
{

    FILE *f;
    int c;
    int index = 0;
    f = fopen(filepath, "rt");
    while((c = fgetc(f)) != EOF){
        fileContent[index] = c;
        index++;
    }
    fileContent[index] = '\0';

}

int main(){
    int clientSocket;
    char buffer[10000];
    struct sockaddr_in serverAddr;
    socklen_t addr_size;

    /*---- Create the socket. The three arguments are: ----*/
    /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);

    /*---- Configure settings of the server address struct ----*/
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(7891);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

    /*---- Connect the socket to the server using the address struct ----*/
    addr_size = sizeof serverAddr;
    connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

    char JSON_STRING[10000];


    readfile("testData.json", JSON_STRING);

    printf("%s", JSON_STRING);


    /*---- Send message to the socket of the incoming connection ----*/
    strcpy(buffer, JSON_STRING);
    send(clientSocket,buffer,10000,0);

    return 0;
}

User avatar
PeterO
Posts: 5073
Joined: Sun Jul 22, 2012 4:14 pm

Re: TCP/IP Communication from PC to RaspberryPi

Thu Dec 20, 2018 4:04 pm

In your client code, you need to set the server IP address.... Here is code taken from an applcation of mine...
Look at the call to "gethostbyname"....

Code: Select all


gboolean initCommsNetwork(void)
{
struct hostent *hp;
struct sockaddr_in E803_server_name;
int n;

    /* Create socket on which to send and recieve. */
    E803_socket = socket(AF_INET, SOCK_STREAM, 0); 
    if (E803_socket < 0) { 
	perror("opening network socket to the E803"); 
	return FALSE; 
    } 

   /* 
   * Getnostbyname() returns a structure including the network address 
   * of the specified host. 
   */

    hp = gethostbyname("192.168.1.21"); 
    if (hp == 0) { 
	fprintf(stderr, "%s: unknown host", "localhost"); 
	return FALSE; 
    } 
  
  bcopy(hp->h_addr, &E803_server_name.sin_addr, hp->h_length); 
  E803_server_name.sin_family = AF_INET; 
  E803_server_name.sin_port = htons(7000);  ; 

  n = connect(E803_socket, (struct sockaddr *)&E803_server_name,
	      sizeof (E803_server_name));
  
  
  if(n == -1)
  {
      perror("E803 connect returned:");
      close(E803_socket);
      E803_socket = -1;
      return FALSE;
  }
  else
  {
	// Set up stuff for reading the socket using glib_g_io library from the gtk event loop
      E803_channel = g_io_channel_unix_new(E803_socket);

      g_io_add_watch(E803_channel,G_IO_IN,peripheral_message,NULL);

      g_io_channel_set_encoding(E803_channel,NULL,NULL);

  }
  return TRUE;
}


Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 3:05 pm

Thank you for your response!

I was not able to work for on this project for the past days, but now I am back working.

I changed my client code as following:

Code: Select all

/****************** CLIENT CODE ****************/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>

void readfile(char* filepath, char* fileContent)
{

    printf("start reading file");
    FILE *f;
    int c;
    int index = 0;
    f = fopen(filepath, "rt");
    while((c = fgetc(f)) != EOF){
        fileContent[index] = c;
        index++;
    }
    fileContent[index] = '\0';

}

int main(){
    int clientSocket;
    char buffer[10000];
    struct hostent *hp;
    struct sockaddr_in serverAddr;
    socklen_t addr_size;


    /*---- Create the socket. The three arguments are: ----*/
    /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);

    /*---- Configure settings of the server address struct ----*/
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(7891);


    hp = gethostbyname("raspberrypi");
    if (hp == 0) {
        fprintf(stderr, "%s: unknown host", "localhost");
        return 0;
    }

    memmove(hp->h_addr, &serverAddr.sin_addr, (size_t) hp->h_length);
    //serverAddr.sin_addr.s_addr = INADDR_ANY;
    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

    /*---- Connect the socket to the server using the address struct ----*/
    addr_size = sizeof serverAddr;
    connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

    char JSON_STRING[10000];


    readfile("testData.json", JSON_STRING);

    printf("%s", JSON_STRING);


    /*---- Send message to the socket of the incoming connection ----*/
    strcpy(buffer, JSON_STRING);
    send(clientSocket,buffer,10000,0);

    return 0;
}

I tried this with the name "raspberrypi" and the actual ip-address "xxx.xxx.x.xxx", both will not work.
Again if I change it to "localhost" and run both server and client in two different shells, everything works.

The server running on the pi seems to not receive any connection. I added some print statements and

Code: Select all

    /*---- Listen on the socket, with 5 max connection requests queued ----*/
    if(listen(welcomeSocket,5)==0)
        printf("Listening\n");
    else
        printf("Error\n");

    printf("t1");
    /*---- Accept call creates a new socket for the incoming connection ----*/
    addr_size = sizeof serverStorage;
    printf("t2");
    newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);


    printf("t3");
    /*---- Read the message from the server into the buffer ----*/
    recv(newSocket, buffer, 10000, 0);

    /*---- Print the received message ----*/
    printf("Data received: %s",buffer);

    return 0;
only "Listening" is printed, nothing else.

User avatar
PeterO
Posts: 5073
Joined: Sun Jul 22, 2012 4:14 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 3:12 pm

Can you "ping" the machines from each other ?
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 3:26 pm

When I use the concrete IP-Addresses I can yes.

On the pi I can ping my working PC and on my working PC I can ping the pi

pfletch101
Posts: 528
Joined: Sat Feb 24, 2018 4:09 am
Location: Illinois, USA

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 3:47 pm

Do you have a firewall (probably as part of an anti-virus suite) on your PC? If you do, it might be worth seeing what happens if you temporarily disable it before trying to run your program. I have a couple of client/server pairs running between a Windows machine and a pi, but they are written in VB.NET (for the Windows clients) and Python (for the pi servers), so the code probably wouldn't help you.

DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 3:53 pm

Deactivating the firewall does not change anything. I tried it an still only "Listening" is printed on the Pi. The client executes and stops correctly after the message was send I guess? Or should the client also be "stuck"?

n67
Posts: 938
Joined: Mon Oct 30, 2017 4:55 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 4:03 pm

You really need to separate the two parts of this issue:

1) Network problems (general knowledge about how TCP/IP works, then things like firewalls, etc)

2) C programming errors - because C is not a friendly programming language and there are all sorts of errors that people can make when attempting to do networking stuff in C.

Since many of the suggestions made in this thread have been oriented towards #1 above, I'd suggest playing around with netcat (or something similar) and making sure that everything is OK on the basic networking front before plunging into the C side of it.

FWIW, from what I can tell, it is likely that this is NOT a "Type 1" problem; I think it is likely to be a "Type 2". But you need to completely eliminate "Type 1" first - if for no other reason than to be able to state it clearly on the thread and thus not get people making suggestions assuming that you are (are having "Type 1" issues).
"L'enfer, c'est les autres"

G fytc hsqr rum umpbq rm qyw rm rfc kmbq md rfgq dmpsk:

Epmu Sn!

J lnacjrw njbruh-carppnanm vxm rb mnuncrwp vh yxbcb!

User avatar
PeterO
Posts: 5073
Joined: Sun Jul 22, 2012 4:14 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 4:23 pm

DuBBox wrote:
Tue Dec 25, 2018 3:26 pm
When I use the concrete IP-Addresses I can yes.

On the pi I can ping my working PC and on my working PC I can ping the pi
Can you post you complete source code so we can compile it and see what is going on.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 4:37 pm

server.c

Code: Select all

/****************** SERVER CODE ****************/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(){
    int welcomeSocket, newSocket;
    char buffer[10000];
    struct sockaddr_in serverAddr;
    struct sockaddr_storage serverStorage;
    socklen_t addr_size;

    /*---- Create the socket. The three arguments are: ----*/
    /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
    welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (welcomeSocket == -1)    {
        printf("Could not create socket");
    }

    /*---- Configure settings of the server address struct ----*/
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(7891);
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    /* Set all bits of the padding field to 0 */
    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

    /*---- Bind the address struct to the socket ----*/
    bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

    /*---- Listen on the socket, with 5 max connection requests queued ----*/
    if(listen(welcomeSocket,5)==0)
        printf("Listening\n");
    else
        printf("Error\n");

    printf("t1");
    /*---- Accept call creates a new socket for the incoming connection ----*/
    addr_size = sizeof serverStorage;
    printf("t2");
    newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);


    printf("t3");
    /*---- Read the message from the server into the buffer ----*/
    recv(newSocket, buffer, 10000, 0);

    /*---- Print the received message ----*/
    printf("Data received: %s",buffer);

    return 0;
}
client.c

Code: Select all

/****************** CLIENT CODE ****************/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>

void readfile(char* filepath, char* fileContent)
{

    printf("start reading file");
    FILE *f;
    int c;
    int index = 0;
    f = fopen(filepath, "rt");
    while((c = fgetc(f)) != EOF){
        fileContent[index] = c;
        index++;
    }
    fileContent[index] = '\0';

}

int main(){
    int clientSocket;
    char buffer[10000];
    struct hostent *hp;
    struct sockaddr_in serverAddr;
    socklen_t addr_size;


    /*---- Create the socket. The three arguments are: ----*/
    /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);

    /*---- Configure settings of the server address struct ----*/
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(7891);


    hp = gethostbyname("192.168.0.241");
    if (hp == 0) {
        fprintf(stderr, "%s: unknown host", "localhost");
        return 0;
    }

    memmove(hp->h_addr, &serverAddr.sin_addr, (size_t) hp->h_length);
    //serverAddr.sin_addr.s_addr = INADDR_ANY;
    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

    /*---- Connect the socket to the server using the address struct ----*/
    addr_size = sizeof serverAddr;
    connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

    char JSON_STRING[10000];


    readfile("testData.json", JSON_STRING);

    printf("%s", JSON_STRING);


    /*---- Send message to the socket of the incoming connection ----*/
    strcpy(buffer, JSON_STRING);
    send(clientSocket,buffer,10000,0);

    return 0;
}
compiling both with

PI:
compile with
$gcc server.c -o server
run with
$./server

PC:
compile with
$gcc client.c -o client
run in cygwin with
$./client
or in windows-shell with
$client.exe

pfletch101
Posts: 528
Joined: Sat Feb 24, 2018 4:09 am
Location: Illinois, USA

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 4:54 pm

A few random thoughts:
1) Is send() synchronous or asynchronous - i.e. does it block until the contents of buffer is actually transmitted, or does it return immediately? If the latter, the fact that the program then ends, presumably closing the connection, may be relevant.
2) Does send() return a value to indicate successful transmission (or not)? If it does, you should check it.
3) Should you be explicitly flushing and/or closing the socket before allowing the sending program to close?

DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 5:42 pm

Just discovered something that seems weird to me:

When I set the address in the client with

Code: Select all

    hp = gethostbyname("xxx.xx......");
    if (hp == 0) {
        fprintf(stderr, "%s: unknown host", "localhost");
        return 0;
    }

    memmove(hp->h_addr, &serverAddr.sin_addr, (size_t) hp->h_length);
and I run server on my local machine, the client sends the message to my local machine. Shouldn't it just send it to "xxx.xx......"? Why localhost also receives this message?

NOTE:
Send returns -1 if something locally goes wrong, this is also returned when I run server on the pi and client on the PC. It is like running client locally and no server. As I mentioned above, running server and client on the local machine still works, even the IP is never mentioned in client, also -1 is not returned in this case.

User avatar
PeterO
Posts: 5073
Joined: Sun Jul 22, 2012 4:14 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 5:50 pm

Here is working (fixed) client.c code...

Code: Select all

    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
    memmove( &serverAddr.sin_addr,hp->h_addr,  hp->h_length);
You have the src and dest the wrong way round in the memmove !

Oh, and you REALLY should check return values from things like connect and send !

Using the code I sent you earlier would have fixed your problem then .

PeterO
Last edited by PeterO on Tue Dec 25, 2018 6:00 pm, edited 2 times in total.
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

pfletch101
Posts: 528
Joined: Sat Feb 24, 2018 4:09 am
Location: Illinois, USA

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 5:54 pm

You seem to have a lot of clues here. all suggesting that the client is still trying to make a 'loopback' connection, even when you (think you have) set things up to connect to the remote server. I assume that the address you are putting in the gethostbyname() call on the client is that of the server?

DuBBox
Posts: 10
Joined: Wed Nov 21, 2018 3:28 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 6:07 pm

Well thank you!
The memmove mistake solved the problem!
I am sorry for this, bcopy did not work on my system somehow it just did nothing at all and caused an infinite running programm, also it is recommended to replace bcopy and so on with memcopy etc. I do not exactly know why, but it is recommended.

Thank you guys for solving my Problem especially PeterO for the demo-code!

User avatar
PeterO
Posts: 5073
Joined: Sun Jul 22, 2012 4:14 pm

Re: TCP/IP Communication from PC to RaspberryPi

Tue Dec 25, 2018 6:20 pm

Yes the manual page for bcopy says "This function is deprecated (marked as LEGACY in POSIX.1-2001): use memcpy(3) or memmove(3) in new programs. "

The code I originally sent you "works for me" ;) and is so old it may predate the legacy marking in posix.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Return to “Beginners”