TCP connection to private server (spark core as tcp client)

i have got spark core and Ubuntu server (192.168.164.3). I am trying to connect spark core (TCP Client) to Ubuntu server (TCP Server) by using TCP 90 port number. But they are not connecting to eachother(i have found it by using tcpdump). Can any body tell me why?
here is the core code:

#include <string.h>
char server[] = { 192, 168, 164, 3 };
TCPClient client;

int ledPin = D5;
int inputPin = D7;
int pirState = LOW;
int val = 0;

void setup()
{
    pinMode(ledPin, OUTPUT);
    pinMode(inputPin, INPUT);
    Spark.variable("inputPin", &inputPin, INT);
    Serial.begin(9600);
    delay(1000);
    Serial.println("connecting...");

    if (client.connect(server, 90))
    {
        Serial.println("connected");
        client.println();
    }
    else
    {
        Serial.println("connection failed");
        client.stop();
    }
}

void loop() 
{
     val = digitalRead(inputPin);
     if (val == HIGH)
    {
        digitalWrite (ledPin, HIGH); // then turn on the LED    
    }
    if (pirState == LOW)
    {
        pirState = HIGH;
    }
    else
    {
        digitalWrite (ledPin, LOW);
        delay(300);
        if (pirState == HIGH)
        {
            pirState = LOW;
        }
    }
}

here is Ubuntu server code:

#include <pthread.h>
#include time.h>
#include stdio.h>
#include stdlib.h>
#include string.h>
#include unistd.h>
#include sys/types.h> 
#include sys/socket.h>
#include netinet/in.h>

#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
#define	LISTENQ		1024	/* 2nd argument to listen() */


void* ClientConnect(void* Unused)
{
	int	listenfd, connfd, *n = (int*) Unused;
	socklen_t	CliLen;
	struct	sockaddr_in servaddr, CliAddr;
	char	buff[MAXLINE];
	char	vector[0];
	time_t	ticks;
	strcpy(vector , "1");
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(90);
	bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
	listen(listenfd, LISTENQ);
	CliLen = sizeof(CliAddr);
	while(*n) 
	{
		connfd = accept(listenfd, (SA *) &CliAddr, &CliLen);
	        write(connfd, vector, strlen(vector));
		close(connfd);
	}
	close(listenfd);
	return 0;
}

int main(int argc, char **argv)
{
	int i=1;
	pthread_t PthreadID;
	pthread_create (&PthreadID, NULL, &ClientConnect, &i);
	while(i)
	{
		printf("print i:\n");
		scanf ("%d",&i);
	}
	pthread_join (PthreadID, NULL);
	return 0;
}```

Hey @ufo567,
Looks like to me with a quick glance, after your client.println() or when you are done doing all your client.prints you would need a client.flush();

And am I correct you are only sending a “\n” ? I am guessing this small amount would require the flush. Give that a whirl.

Good Luck!

hi, Some​Fix​It​Dude.

The problem is that sparkcore doesn’t send any packets to server before doing client.println. Why it is not sending i can not understand.

This line in setup() is the only time I can see that you send to the TCP connection. So I would expect this code to send one packet with a single newline in it right after your core starts breathing cyan.

Did you want to send more to the server?

client.flush() flushes the receive side (bytes into the core) and is good for throwing away data you don't want to read. I do that in HTTP connections when I send a new GET request since I don't really any old responses.

So I am not aware if you tried any basic connectivity tests. Can you ping the spark core from the server? Can the core ping the server? Basic connectivity test, just change the ip address from google to your ubuntu server in this app: https://github.com/SomeFixItDude/Spark_Core/tree/master/TestInfo

Next I would crack open putty and telnet to the ubuntu server on port 90 and send some data manually. Make sure that is working. If that works then most likely your iptables is fine but maybe verify you don’t have any specific ip address rules for that port.

If that all works we’ll go from there.

-Bri

Port 90 is a privileged port. You need to run the Ubuntu program as root. I think there may be other bugs (vector is not long enough?) so I cut down your code to this:

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

#define SA      struct sockaddr


void ClientConnect(void)
{
        int     listenfd, connfd;
        socklen_t       CliLen;
        struct  sockaddr_in servaddr, CliAddr;
        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(90);
        bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
        listen(listenfd, 1);
        CliLen = sizeof(CliAddr);
        while(1) 
        {
                connfd = accept(listenfd, (SA *) &CliAddr, &CliLen);
                write(connfd, "1", 1);
                close(connfd);
        }
}

int main(int argc, char **argv)
{
        ClientConnect();
}

If you run it as root you will see that sudo netstat -l --inet -n -p shows the program listening on port 90. If run as an ordinary user a random port >= 1024 is the one being listened to. You need to check the return code of bind() and the other system/library calls. It makes the code look untidy, but it’s necessary. A failed Unix system/library call does not (typically) stop your program.

1 Like

The problem was in the type of variable:
in my code:
char server[] = { 192, 168, 164, 3 };
must be:
byte server[] = { 192, 168, 164, 3 };
and it is much more easier to use the following command:
netstat -an | grep -i PORTNUMBER
Now i am investigating in sending information between my linux server and core. I will write my script of connecting here.

2 Likes

Hi @ufo567

Good catch–I guess we all missed that one looking at your code. char is a signed type so 127
-128 are the legal values. byte and uint8_t and unsigned char are all 8-bit unsigned types, but uint8_t is the most universal 8-bit type for portable code because it is explicit.

1 Like

hi, everybody.

I have tried to investigate connection. so i changed the code to the following view:
// SYNTAX
//TCPClient client;
// EXAMPLE USAGE

TCPClient client;
byte server[] = { 192, 168, 164, 3 }; // Google
void setup()
{
Serial.begin(9600);
delay(1000);
Serial.println(“connecting
”);

if (client.connect(server, 2088))
{
Serial.println(“connected”);
client.println(“GET /search?q=unicorn HTTP/1.0”);
client.println(“Host: www.google.com”);
client.println(“Content-Length: 0”);
client.println();
}
else
{
Serial.println(“connection failed”);
}
}

void loop()
{
if (client.available())
{
Serial.println(“connected”);
char c = client.read();
Serial.print©;
}

if (!client.connected())
{
Serial.println();
Serial.println(“disconnecting.”);
client.stop();
for(;:wink:
{
Serial.println(“connection failed”);
}
}
}

it is an example from spark.io
and at the same time on my server i processed the following console command:
tcpdump dst port 2088
and i have not saw any TCP SYNC, ACK segments.
But i saw arp request and answer from spark by using wireshark, but not more.
and core always writes on console: “connected”.
Although core always writes on console: “connected” - even when Ubuntu is powered off

but when i changed the code to the following:
TCPClient client;
byte server[] = { 192, 168, 164, 3 };
void setup()
{
Serial.begin(9600);
delay(1000);
Serial.println(“connecting
”);

if (client.connect(server, 2088))
{
Serial.println(“connected”);
client.println(“connected”);
}
else
{
Serial.println(“connection failed”);
}
}

void loop()
{
if (client.connected())
{
Serial.println(“connected”);
char c = client.read();
Serial.print©;
}
else
{
Serial.println();
Serial.println(“disconnecting.”);
client.stop();
for(;:wink:
{
Serial.println(“connection failed”);
}
}
}
i always get “connection failed”.

Can anybody explain me what is the problem in?

On the Ubuntu box something is listening on port 80 and nothing is listening on port 2088.

(tcpdump doesn’t make one side of the connection, it simply monitors the packets between the two endpoints)

What is listening on port 80? I guess Apache? The HTTP protocol doesn’t say anything to the client immediately so you won’t be able to read() without first write()ing.

Is it still your own program on the Ubuntu box, the one you posted previously? I would like to eliminate that from the problem. I don’t have a spare Spark right now so I cannot test your code directly. But I guess you will have postfix or similar running on the Ubuntu box. Have you tried connecting to SMTP port 25 there? The first thing it does is output a “220 
” and you should see that. Perhaps first, from elsewhere, do a “telnet 192.168.164.3 25” to check there is a mail client listening. If you see the 220 message then so should the Spark.

1 Like

i have changed the code
and it seems to work correctly.
here is the code:

sparc core:

TCPClient client;
byte server[] = { 192, 168, 164, 3 };
byte c;
int port = 2089;
void setup()
{
  Serial.begin(9600);
  delay(1000);
  Serial.println("connecting...");
}

void loop()
{
      Serial.println("connecting...");
  if (client.connect(server, port))
  {
    Serial.println("connected");
    client.println("connected");
//    с = client.read();
    Serial.print(client.read());
  }
  else
  {
    Serial.println("connection failed");
  }
  Serial.println();
  Serial.println("disconnecting.");
  client.stop();
}

ubuntu server:

#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
#define	LISTENQ		1024	/* 2nd argument to listen() */


void* ClientConnect(void* Unused)
{
	int	listenfd, connfd, *n = (int*) Unused;
	socklen_t	CliLen;
	struct	sockaddr_in servaddr, CliAddr;
	char	buff[MAXLINE];
	char	vector[0];
	time_t	ticks;
	strcpy(vector , "1");
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(2089);
	bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
	listen(listenfd, LISTENQ);
	CliLen = sizeof(CliAddr);
	while(*n) 
	{
		connfd = accept(listenfd, (SA *) &CliAddr, &CliLen);
	        write(connfd, vector, strlen(vector));
		close(connfd);
	}
	close(listenfd);
	return 0;
}

int main(int argc, char **argv)
{
	int i=1;
	pthread_t PthreadID;
	pthread_create (&PthreadID, NULL, &ClientConnect, &i);
	while(i)
	{
		printf("print i:\n");
		scanf ("%d",&i);
	}
	pthread_join (PthreadID, NULL);
	return 0;
}

i hope it would be helpful)))

Can you please blockquote the code as preformatted as I think some chars are getting mangled. I would like to cut'n'paste. On the interface I see you highlight the code and then press the "</>" symbol.

1 Like

can you send me your e-mail, and then i will send you the code by e-mail.
this forum makes terrible my copy past.

But there is some problem in my code, now my console shows me the following:

connecting...
connected
-1
disconnecting

it is because it didn't wait for message.

i see in my tcpdump
192.168.164.69 (spark core) syn -> 192.168.164.3 (Ubuntu server)
192.168.164.3 (Ubuntu server) syn, ack -> 192.168.164.69 (SparkCore)
192.168.164.69 (spark core) ack -> 192.168.164.3 (Ubuntu server)
192.168.164.69 (spark core) fin -> 192.168.164.3 (Ubuntu server)

i will try by using delay, i hope it will help me.

As I said, if you use use press the “</>” button highlighted code format is preserved. You can re-edit a previous posting.

I think your Ubuntu code is wonky. In order to see if the Spark code is working correctly try connecting to port 25, but first telnet there to check there is something listening.

I note your port moved from 2088 in one version of your code to 2089. I wonder if 2088 was blocked by a version of your prog still running, and if you now were to edit your progs for 2090 it would still work, until you tried it again.

I think also trying to work it all out from 1st principles by watching a packet trace is not the quickest way to get this fixed.

sorry, but button “</>” haven’t helped me.
So you can download the code by using my dropbox:

at the moment i have insered delay
and now i am getting:

connecting

connected
49
disconnecting

and some times still:

connecting

connected
-1
disconnecting

does anybody know why?

Hi @ufo567

I fixed up your code above with the pre-formated code markup, which is hard to type out here but is three grave accents followed by cpp on a line by itself above the code, and then three grave accents below the code on a line by itself.

If you edit your post above, you can see how it works.

2 Likes

thanks, many thanks!

What does the scanf() do? “49” - you realise it’s ascii for ‘1’ which is the char sent? What is your intention? I still worry that the Ubuntu side is wonky. Why is vector dimensioned to zero? Won’t you try your spark client against Ubuntu’s port 25? Why does the spark client only want to read one char and then close the connection? Too puzzling. What do you expect while(*n) to do when you have *n = (int*) Unused; ? Unused is just 1? That it doesn’t work seems almost the intention! Almost deliberately obfuscated.

As I wrote before you need to test the result of each of your system and library calls. e.g.

#include <errno.h>
#include <stdio.h>
int rc;
.
.
.
rc = listen( ...);
if( rc == -1) {
  perror("listen");
  exit(1);
}
.
.
rc = accept( ...);
if( rc == -1) {
  perror("accept");
  exit(1);
}
connfd = rc;

On my Ubuntu box your LISTENQ should be no more than 1000 or maybe 128. See man 7 socket, man 2 listen and /proc/sys/net/core/netdev_max_backlog and /proc/sys/net/ipv4/tcp_max_syn_backlog

Perhaps you run out of resources. Try setting LISTENQ to 10

#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

#define	MAXLINE		1	/* max text line length */
#define	SA	struct sockaddr
#define	LISTENQ		3	/* 2nd argument to listen() */


void* V_F_ClientConnect (void* V_SomeData)	//V_SomeData - data wich to send to the client.
/*
	V_F_ClientConnect - creates connection for TCP clients (spark core) to send data from server to spark core.
*/
{
	int I_Error_2;	//error indicator.
	int	I_SocketID, I_ConnectionIDWr, *n = (int*) V_SomeData;	//I_SocketID - socket ID, I_ConnectionIDWr - ID of connection for writing data to client.
	socklen_t	S_SL_t_CliLen;	//S_SL_t_CliLen - IP address length.
	struct	sockaddr_in S_SA_i_ServAddr, S_SA_i_CliAddr;	//S_SA_i_ServAddr - server IP address ,S_SA_i_CliAddr - client IP address.
	char	C_Vector[1];	//C_Vector - data wich to send to the client.
	strcpy (C_Vector , "1");
	I_SocketID = socket (AF_INET, SOCK_STREAM, 0);
	I_Error_2 = I_SocketID;
	if (I_Error_2 == -1)
	{
		perror ("\nV_F_ClientConnect function, socket (AF_INET, SOCK_STREAM, 0) calling error\n The following error occurred:");
	}
	bzero(&S_SA_i_ServAddr, sizeof(S_SA_i_ServAddr));	//shall place sizeof(S_SA_i_ServAddr) zero-valued bytes in the S_SA_i_ServAddr.
	/*
		no errors defined for bzero
	*/
	S_SA_i_ServAddr.sin_family      = AF_INET;	//socket works in IPv4 network type.
	S_SA_i_ServAddr.sin_addr.s_addr = htonl(INADDR_ANY);	//all clients can connect.
	S_SA_i_ServAddr.sin_port        = htons(20901);	//Server will listen TCP port
	I_Error_2 = bind(I_SocketID, (SA *) &S_SA_i_ServAddr, sizeof(S_SA_i_ServAddr));	//binding socket to port
	if (I_Error_2 !=0)
	{
		perror ("\nV_F_ClientConnect function, bind(I_SocketID, (SA *) &S_SA_i_ServAddr, sizeof(S_SA_i_ServAddr)) calling error\n The following error occurred:");
	}
	I_Error_2 = listen(I_SocketID, LISTENQ);	//server starts listening TCP port
	if (I_Error_2 !=0)
	{
		perror ("\nV_F_ClientConnect function, listen(I_SocketID, LISTENQ) calling error\n The following error occurred:");
	}
	S_SL_t_CliLen = sizeof(S_SA_i_CliAddr);
	while(*n) 
	{
		I_ConnectionIDWr = accept(I_SocketID, (SA *) &S_SA_i_CliAddr, &S_SL_t_CliLen);
		I_Error_2 = I_ConnectionIDWr;
		if (I_Error_2 == -1)
		{
			perror ("\nV_F_ClientConnect function, accept(I_SocketID, (SA *) &S_SA_i_CliAddr, &S_SL_t_CliLen) calling error\n The following error occurred:");
		}
		C_Vector[0] = *n;
	        if (write (I_ConnectionIDWr, C_Vector, strlen(C_Vector)) ==-1)
		{
			perror ("\nV_F_ClientConnect function, write (I_ConnectionIDWr, C_Vector, strlen(C_Vector)) calling error\n The following error occurred:");
		}
		printf("\n you have printed %d\n", *n);
		if (close(I_ConnectionIDWr) == -1)
		{
			perror ("\nV_F_ClientConnect function, close(I_ConnectionIDWr) calling error\n The following error occurred:");
		}
	}
	if (close(I_SocketID) == -1)
	{
		perror ("\nV_F_ClientConnect function, close(I_SocketID) calling error\n The following error occurred:");
	}
	return 0;
}

int main(int argc, char **argv)
/*
	create a therad (V_F_ClientConnect) for sending data from console to client, console managed from the main finction.
*/
{

	int I_Error;	//error indicator.
	int I_MainFuncEnd = 1;	//I_MainFuncEnd = 0 - main function end, I_MainFuncEnd != 0 - main finction continues and sends I_MainFuncEnd value throught the TCP socket.
	pthread_t PthreadID;	//ID of the thread.
	I_Error = pthread_create (&PthreadID, NULL, &V_F_ClientConnect, &I_MainFuncEnd);	//creating thread and calling V_F_ClientConnect(I_MainFuncEnd) finction.
	if (I_Error != 0)
	{
		perror ("\nmain function, pthread_create (&PthreadID, NULL, &V_F_ClientConnect, &I_MainFuncEnd) calling error\n The following error occurred:");
	}
	while (I_MainFuncEnd)
	{
		printf("\nprint I_MainFuncEnd:\n");
		scanf ("%d",&I_MainFuncEnd);
	}
	I_Error = pthread_join (PthreadID, NULL);
	if (I_Error != 0)
	{
		perror ("\nmain function, pthread_join (PthreadID, NULL) calling error\n The following error occurred:");
	}
	return 0;
}