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

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!

Related

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));
}

aio_write does not work in my simple client/server proggram

I am starting to use aio to write a simple client server program.My client program:
int main(int argc, char const *argv[])
{
int port = 6000;
struct sockaddr_in my_address;
memset(&my_address, 0, sizeof(my_address));
my_address.sin_family = AF_INET;
my_address.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1
my_address.sin_port = htons(port);
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, (struct sockaddr*)&my_address, sizeof(my_address));
char * str = "hello";
struct aiocb my_aio;
memset((void*)&my_aio, 0, sizeof(struct aiocb));
my_aio.aio_fildes = fd;
my_aio.aio_buf = str;
my_aio.aio_nbytes = strlen(str);
aio_write(&my_aio);
return 0;
}
My server program:
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");
}
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);
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;
}
I expect my server side to print out hello, but it does not. Thanks in advance.
Your code works otherwise, but your main is exited before the asynchronous write has completed; thus the socket is closed before the completion of asynchronous write. I did as little as add a perror("aio_write") after the aio_write call to find out what error it was giving if any, and now hello was successfully sent to the server.
You'd probably want to use aio_suspend to ensure that any outstanding operations are completed before exiting the main.

first client request not being served in sockets in c

This is a simple iterative client-server program. Where the server prints out "Received request" on successful establishment of connection.
server side
#define LENGTH 256
#define SERV_PORT 4000
#define LISTENQ 8
int main()
{
int listenfd, connfd, n;
socklen_t clilen;
char buf[LENGTH];
struct sockaddr_in cliaddr, servaddr;
//creation of socket
listenfd = socket (AF_INET, SOCK_STREAM, 0);
//creating socket address
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
// printf("\nServer running.. waiting for connections");
// listen(listenfd, LISTENQ);
for(; ;)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("\nReceived request");
//sleep(5);
}
return 0;
}
client side
#define LENGTH 256
#define SERV_PORT 4000
int main( int argc, char *argv[])
{
int sock;
struct sockaddr_in server;
struct hostent *hp;
char buff[256];
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket failed");
exit(1);
}
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if(hp == 0)
{
perror("gethost by name failed");
exit(1);
}
memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
server.sin_port = htons(4000);
if(connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
{
perror("\nconnect failed");
exit(1);
}
return 0;
}
When I run this multiple client-server code, the output for first client is different from the preceding clients. I need the first client to output like others. Can someone help?
When the first client establishes a connection with the server, the server doesn't output "Received request", where as, for the other clients do output "Received request".
You need to restore the listen() call. – EJP

Print my ip TCP server C

I'm writing a two way chat in C, but what I'd really like to do is have the chat server print the ip of the host when it starts up. My code thus far looks like this:
#include<stdio.h> //printf
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define PORT 8888 //The port on which to listen for incoming data
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(void)
{
struct sockaddr_in serv_addr, cli_addr;
int sockfd, newsockfd, n;
socklen_t cli_len;
char buffer[512];
char message[512];
//create a socket
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR OPENING SOCKET");
// zero out the structure
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
//bind socket to port
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR ON BINDING");
//keep listening for data
//inet_ntoa(serv_addr.sin_addr)
inet_ntop(AF_INET, &serv_addr.sin_addr.s_addr, buffer, sizeof(serv_addr));
listen(sockfd,5);
printf("Listening on ip %s and port %d\n", buffer, ntohs(serv_addr.sin_port));
while(1)
{
cli_len = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
if (newsockfd < 0) error("ERROR ON ACCEPT");
while(1)
{
bzero(buffer,512);
n = read(newsockfd,buffer,511);
if(n < 0) error("ERROR READING FROM SOCKET");
printf("Friend: %s\n" , buffer);
//now reply
printf("Please enter the message: ");
bzero(buffer,512);
fgets(buffer,511,stdin);
n = write(newsockfd,buffer, strlen(buffer));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
}
close(sockfd);
return 0;
}
Currently when I make and run it immediately prints
Listening on ip 0.0.0.0 and port 8888
This really should be simple. I realize that it's binding to all interfaces, so it's accurate that 0.0.0.0 is the ip.
Is there any way to have it show a host ip? Am I looking at pinging the DNS to lookup ip by hostname and then print that? Any other suggestions?
Thanks
I found a solution. My code now looks like this:
#include<stdio.h> //printf
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#define PORT 8888 //The port on which to listen for incoming data
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(void)
{
struct sockaddr_in serv_addr, cli_addr;
int sockfd, newsockfd, n;
socklen_t cli_len;
char buffer[512];
char message[512];
char sZhostName[255];
gethostname(sZhostName,255);
struct hostent *host_entry;
host_entry = gethostbyname(sZhostName);
//create a socket
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR OPENING SOCKET");
// zero out the structure
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = INADDR_ANY;
//bind socket to port
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR ON BINDING");
//keep listening for data
listen(sockfd,5);
printf("Listening on ip %s and port %d\n", inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list), ntohs(serv_addr.sin_port));
while(1)
{
cli_len = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
if (newsockfd < 0) error("ERROR ON ACCEPT");
while(1)
{
bzero(buffer,512);
n = read(newsockfd,buffer,511);
if(n < 0) error("ERROR READING FROM SOCKET");
printf("Friend: %s\n" , buffer);
//now reply
printf("Please enter the message: ");
bzero(buffer,512);
fgets(buffer,511,stdin);
n = write(newsockfd,buffer, strlen(buffer));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
}
close(sockfd);
return 0;
}
I used this article: https://suite.io/guy-lecky-thompson/7sd21g
There are suggestions around that getaddrinfo() replaces the gethostname()/gethostbyname() method, including in the famous Beej's guide, but I have not found out how to do this yet.

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