Raspberry PI multi-threaded socket issue C - c

so i have a very basic tcp server which has two threads listening on two separate ports. However, when the code runs the second thread is never created and it appears that the first thread is actually blocking the whole program from creating the next thread. Here is the code... (quite simple)
void *Listener1();
void *Listener2();
int main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL,Listener1(), NULL);
pthread_create(&thread2, NULL,Listener2(), NULL);
sleep(50);
return 0;
}
void *Listener1()
{
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
puts("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(12346);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
puts("ERROR on binding");
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
puts("ERROR on accept");
else
puts("Client connected!");
close(newsockfd);
close(sockfd);
return 0;
}
void *Listener2()
{
puts("hi)");
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
puts("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(12345);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
puts("ERROR on binding");
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
puts("ERROR on accept");
else
puts("Client connected!");
close(newsockfd);
close(sockfd);
return 0;
}

Cake a close look at
pthread_create(&thread1, NULL,Listener1(), NULL);
// ^^
// causes the function to be called
Here you don't pass a pointer to the Listener1 function, you are actually calling it, and its returned value would be used as the function pointer to the thread function, if it ever returned.
You should instead pass a pointer to the function:
pthread_create(&thread1, NULL,&Listener1, NULL);

Related

How to fix this client-server code to print to stdout?

I'm trying to write a client-server program in C. For now I have a connection between the server and the client but for some reason nothing happens or prints after the "connected" print.
I've tried sample printing before and after the "connected" but nothing shows on my shell.
my server:
int main(void)
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);//Af_INet is protocol tcp np? ip? - this creates an empty socket
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
{
printf("setsockopt failed\n");
exit(0);
}
// calls to bind(), listen() and accept() here
memset((char *) &serv_addr, 0, sizeof(serv_addr));
portno = 8888;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("bind failed\n");
exit(0);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
printf("accept failed\n");
exit(0);
}
//end calls
printf("[Server] Connected\n"); // nothing prints before or after this
int n;
char query[BUFFER_SIZE]={0};
char result[BUFFER_SIZE]={0};
char *hello = "Hello from client";
send(newsockfd, hello , strlen(hello) , 0 ); //write also doesn't work
printf("Hello message sent\n");
n = read( newsockfd, query, BUFFER_SIZE);
printf("%s\n",query );
close(newsockfd);
close(sockfd);
my client:
int main(void)
{
int sockfd, portno;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
//get host and connect
portno = 8888;
server = gethostbyname("localhost");
if (server == NULL)
{
printf("gethostbyname failed\n");
exit(0);
}
memset((char *)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((void*)&serv_addr.sin_addr.s_addr, (void*)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("connect failed\n");
exit(0);
}
//end connect
printf("client here");//doesn't show on shell screen
printf("[Client] Connected\n");//shows on shell screen
int n;
char *hello = "Hello from client";
char query[BUFFER_SIZE]={0};
char result[BUFFER_SIZE]={0};
send(sockfd, hello, strlen(hello), 0);
printf("Hello message send\n");
n=read(sockfd,query,BUFFER_SIZE);
printf("%s\n",query);
close(sockfd);
I compile these with:
gcc -Werror -std=c99 server.c -o server
gcc -Werror -std=c99 client.c -o client
Also, I ran ./server before ./client , the shell screens show "Connected" on both client and server screens and that's it no matter what I write on the screen (either client's or server's)
Any help would be appreciated!

C posix sockets, can't send data from client to server

I want to make a client and connect it to a server. I know that client process starts running before server so I do connection in infinite loop until it will be accept. Then I want to enter messages to client and send them to server, which will print them on screen. I removed all error detection from code to make it shorter, I know they have to be there. I am trying to do it like this, but server receives nothing and client can't do second connection.
Server
int main(int argc, char *argv[])
{
int sockfd, newsockfd;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(5000);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
listen(sockfd, 5);
clilen = sizeof(cli_addr);
while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0)
{
read(newsockfd, buffer, 255);
close(newsockfd);
}
close(sockfd);
return 0;
}
Client
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr;
char buffer[256];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(5000);
while (1) {
while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) {
printf("trying to connect\n");
sleep(1);
}
printf("connected\nplease, enter a message\n");
scanf("%s", buffer);
write(sockfd, buffer, strlen(buffer));
}
close(sockfd);
return 0;
}
I don't know just how you've compiled your code but if you had set up the warning flag (-Wall in gcc) you would have gotten this warning
server.c: In function ‘main’:
server.c:33:44: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) {
Acting by it, I changed, this ..
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) {
To .. (notice the extra parentheses)
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) {
I got no more additional warnings, and the server caught the client's message.
Here is the server I ran while debugging this (This is basically your code with slight alterations)
int sockfd, newsockfd;
socklen_t clilen;
char buffer[256];
int nbytes = 0;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
//serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(5007);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
if (listen(sockfd, 5) <0) { }
clilen = sizeof(cli_addr);
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) {
while ((nbytes = read(newsockfd, buffer, sizeof(buffer)))<0) {
sleep(1);
}
printf("client sent: %s", buffer);
}
close(newsockfd);
close(sockfd);
return 0;
Another problem was that we have to create socket each time we do connect in client, like:
while (1) {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) {
printf("trying to connect\n");
sleep(1);
}
printf("connected\nplease, enter a message\n");
scanf("%s", buffer);
write(sockfd, buffer, strlen(buffer));
}

Raspberry PI multiple ethernet server listener

I have a simple TCP server listener program running on the third generation raspberry pi. The PI has two ethernet ports:
eth0:-
ip: 10.0.0.100
Bcast: 10.255.255.255
Subnet mask: 255.0.0.0
eth1:-
ip: 10.0.0.110
Bcast: 10.255.255.255
Subnet mask: 255.0.0.0
My program must listen on both IP addresses on specific ports (code below). However, when I attempt to connect to to either of the ip addresses i can't. But if i remove an ethernet cable from the PI and only have the one, then I can connect to that specific IP. Not sure why this is happening.
void *Listener1();
void *Listener2();
int main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL,&Listener1, NULL);
pthread_create(&thread2, NULL,&Listener2, NULL);
sleep(50);
return 0;
}
void *Listener1()
{
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
puts("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("10.0.0.100");
serv_addr.sin_port = htons(12346);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
puts("ERROR on binding");
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
puts("ERROR on accept");
else
puts("Client connected!");
close(newsockfd);
close(sockfd);
return 0;
}
void *Listener2()
{
puts("hi)");
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
puts("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("10.0.0.110");
serv_addr.sin_port = htons(12345);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
puts("ERROR on binding");
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
puts("ERROR on accept");
else
puts("Client connected!");
close(newsockfd);
close(sockfd);
return 0;
}

How to call bufferevent_write several times?

I am a newbie in libevent, my program below is quite simple. I want to call bubufferevent_write several times, but is seems that it works only for the 1st time.
int main(int argc, char const *argv[])
{
struct sockaddr_in serv_addr;
struct hostent *server;
int portno = atoi(argv[2]);
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
struct event_base* base = event_base_new();
evutil_socket_t fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
struct bufferevent* con_conn = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(con_conn,NULL,NULL,NULL,NULL);
bufferevent_enable(con_conn,EV_READ|EV_WRITE|EV_PERSIST);
bufferevent_socket_connect(con_conn,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
int enable = 1;
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
printf("TCP_NODELAY SETTING ERROR!\n");
char data[5] = "sss";
int i;
for (i = 0; i < 2; ++i)
{
int rc = bufferevent_write(con_conn,data,5);
printf("rc is %d\n", rc);
}
event_base_dispatch(base);
return 0;
}
My server side:
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
//exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
printf("waiting...\n");
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
sleep(5);
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
return 0;
}

lpthread libary difference between Solaris and GNU/Linux when linking with gcc

In Linux(Debian 7), when I run the server, the pointer to array *arg for *doSomething it crashes with segmentation fault.
(Line int *arg = malloc(sizeof(*arg));)
When I run the same code in Solaris, it runs like a charm.
Everything is compiled at its own respective OS (running at Solaris, compiled at Solaris, etc) with no errors or warnings.
A code snippet of the main body of the server without the doSomething method
int main(int argc, char *argv[])
{
int sockfd, portno,pErr;
socklen_t clilen;
//char buffer[256];
//char servPlay[10];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on binding");
while(1) {
int newsockfd;
printf("Listening\n");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("Client %s connected\n", inet_ntoa(cli_addr.sin_addr));
int *arg = malloc(sizeof(*arg));
if(arg ==NULL) {
fprintf(stderr, "No memory for thread\n");
}
*arg=newsockfd;
pErr = pthread_create(NULL,NULL,doSomething,arg);
if(pErr!=0)
{
error("Cannot cread thread\n");
//break;
}
}
close(sockfd);
return 0;
}
More probably than not mnunberg hit the mark and the crash happens in pthread_create() rather than the line you think.
man pthread_create:
Before returning, a successful call to pthread_create() stores the
ID of the new thread in the buffer pointed to by thread; this identifier
is used to refer to the thread in subsequent calls to other pthreads
functions.
It would be pointless allowing to pass a NULL pointer as the first argument (thread).

Resources