Gethostbyname returns NULL after 1021th request - c

Hello I'm sending requests in cycle and then processing them, I have to make that until the program's not stopped by the user. I have to use UDP and after testing on localhost after 1020 requests I get error in gethostbyname, it returns NULL
int sockfd, portno, n, serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
portno = my_port;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
server = gethostbyname(my_host);
bzero(buf, BUFSIZE);
if (sockfd < 0) {
error("ERROR opening socket");
}
if (server == NULL) {
fprintf(stderr,"ERROR, no such host as %s\n", my_host);
exit(0);
}
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serveraddr.sin_addr.s_addr, server->h_length);
serveraddr.sin_port = htons(portno);
serverlen = sizeof(serveraddr);
n = sendto(sockfd, packet, myArraySize, 0, (struct sockaddr *)&serveraddr, serverlen);
if (n < 0) {
error("ERROR in sendto");
}
n = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *)&serveraddr, &serverlen);
if (n < 0) {
error("ERROR in recvfrom");
}
I found nothing about this behavior, and if I'm not using the localhost then I get the error after just 120 requests.

Most likely explanation is that each process on your system is only allowed to have 1024 open file descriptors at a time. 3 of those are reserved for stdin, stdout and stderr.
So the problem is that each time you call gethostbyname, you create a new sockfd, but the code doesn't close the socket when it's done with it.

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

socket API: accept method didn't set sockaddr_in structure

I'm developing client-server software. On server's side I use this code:
int listener_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listener_socket < 0)
{
perror("opening socket error");
return;
}
/* set option for reuseaddr */
int mtrue = 1;
if(setsockopt(listener_socket,SOL_SOCKET,SO_REUSEADDR,&mtrue,sizeof(int)) != 0)
{
perror("setsockopt error");
return;
}
struct sockaddr_in serv_addr, cli_addr;
bzero((char *) &serv_addr, sizeof(serv_addr));
bzero((char *) &cli_addr, sizeof(cli_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* bind socket */
if (bind(listener_socket,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
{
perror("binding error");
return;
}
/* start listening */
listen(listener_socket,connections_limit);
int newsockfd;
/* infinite cycle */
while(1){
newsockfd = accept(listener_socket,(struct sockaddr*) &cli_addr,&clilen);
...
}
So my code blocks in accept() method and waiting for the new connection. When client connects, accept method returns correct non-negative socket descriptor (i can communicate with client using this descriptor) but it doesn't fill cli_addr structure. It remains zeroes. Why it happens?
i forgot this line before accept:
clilen = sizeof(cli_addr);

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

my server pauses at no reason until I kill the client

when i run both client and server i get this as result:
on server
Server is on
Client: XXX.X.X.X accepted
(that's the point that the program pauses until I type ctrl+C in client)
I try to get in while
I get in while
Client
AI Choise:Scissor
AI:Wins ratio 0,Looses ratio 0,Ties ratio 1
I get in while
Client
AI Choise:Scissor
AI:Wins ratio 0,Looses ratio 0,Ties ratio 2
on client
1)--> Paper
2)--> Scissor
3)--> Rock
4)--> Quit
^C
my code:
Server:
int main(int argc, char *argv[]){
printf("\nServer is on\n");
int sockfd, newsockfd, portno;
socklen_t clilen;
int Client_Choice;
struct sockaddr_in serv_addr, cli_addr;
int n,Who_Wins;
int ai_wins=0,ai_looses=0,ties=0,total=0,ai_win_ratio=0,ai_looses_ratio=0,ai_ties_ratio;
time_t t;
srand((unsigned) time(&t));
if (argc < 2) {
fprintf(stderr,"\nERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
error("\nERROR opening socket\n",sockfd);
}
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("\nERROR on binding\n",sockfd);
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
if (newsockfd < 0){
error("\nERROR on accept\n",sockfd);
}
char *cli_IP = malloc(sizeof(cli_addr.sin_addr.s_addr));
if (!cli_IP){
error("\nCould not allocate memory for conversion.\n",sockfd);
}
inet_ntop( AF_INET , &cli_addr.sin_addr.s_addr , cli_IP , INET_ADDRSTRLEN );
printf("\nClient: %s accepted\n",cli_IP);
printf("I try to get in while");
while(Client_Choice!=4){
printf("I get in while");
n= read( newsockfd, &Client_Choice, sizeof(Client_Choice) );
if(n < 0) {
error("\nERROR reading from socket\n",sockfd);
}
.
.
.
}
close(newsockfd);
close(sockfd);
return 0;
}
client
int main(int argc, char *argv[]){
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int send;
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket\n");
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
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);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
error("ERROR connecting\n");
}
while(send < 1 ||send > 4){
printf("\n\t1)--> Paper\n\t2)--> Scissor\n\t3)--> Rock\n\t4)--> Quit\n");
scanf("%d",&send);
n = write(sockfd,&send,sizeof(send));
if (n < 0){
error("ERROR writing to socket\n");
}
n = read(sockfd,&send,sizeof(send));
if (n == 0){
error("ERROR reading from socket\n");
}
}
close(sockfd);
return 0;
}
Your server is blocked waiting the message from the client. You have not reserved resources for dealing with several clients and only have a single process serving a single client (using the connection socket from accept(2)). That's the reason of it to appear blocking. In a normal server scenario, a new process is spawned by a fork(2) system call to deal with the socket obtained from accept(2) while the main process continues to accept(2) connections on the socket used for accepting new connections. As you are dealing with two sockets in server, but not attending the socket descriptor where accept(2) connections come in, it appears to be blocked, but it is actually ready to accept the commands from the active client. This is what is called a sequential server (it doesn't allow a connection before the first one terminates).
By the way, send is uninitialized before use in first while (send < 1 || send > 4) sentence so in case you get it casually equal to 2 (for example) you won't get client code into the while at all. This is only a point, probably there will be more. Why have you used different names for the message type interchanged between server and client? this makes more difficult to search for errors.

recvfrom() not blocking

For some reason my recvfrom() function for sockets is not blocking on my server code like it is supposed to. I am making a basic UDP server to create a rolling session key system.
What am I doing wrong here? It continues on after this line (before i put the (n < 1)) and was crashing. I am pretty sure recvfrom() is supposed to stop the execution of the program until it gets something from the client...
int sockfd, portNumber;
socklen_t clilen;
char buffer[BUFFER_LENGTH];
struct sockaddr_in serv_addr, from;
int n;
// Invalid arguments
if (argc < 2)
exit(0);
else if (atoi(argv[1]) > 65535 || atoi(argv[1]) < 1)
exit(0);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("Error opening socket.\n");
exit(0);
}
// Taken from reference
bzero((char *) &serv_addr, sizeof(serv_addr));
portNumber = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portNumber);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
printf("ERROR on binding.\n");
close(sockfd);
exit(0);
}
// Get initial session key request
int fromlen = sizeof(struct sockaddr_in);
n = recvfrom(sockfd, buffer, BUFFER_LENGTH, 0, (struct sockaddr *)&from, &fromlen);
if (n < 0)
{
printf("Error in receiving.\n");
exit(1);
}
Thanks
You're trying to use a stream socket for UDP;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
What you mean to do is probably;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
Trying to do recvfrom on an unconnected stream socket will most likely return immediately with an error. Next time, you may want to check errno for a hint.

Resources