Saad Rafey
Saad Rafey

Reputation: 551

Issue regarding accept() in socket server client programming in C (Linux)

I have written a server and client program using socket in C in Linux.

Codes are given below:

Server Code:

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write

int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , read_size;
struct sockaddr_in server , client;
char client_message[2000];

//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
    printf("Could not create socket");
}
puts("Socket created");

//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );

//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
    //print the error message
    perror("bind failed. Error");
    return 1;
}
puts("bind done");

//Listen
listen(socket_desc , 3);

//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);

//accept connection from an incoming client
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
    perror("accept failed");
    return 1;
 }
puts("Connection accepted");
  close(client_sock);
  puts("I am at While loop");
  while(1)
    {
    }
return 0;
}

Client Code:

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];

//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
    printf("Could not create socket");
}
puts("Socket created");

server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );

//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
    perror("connect failed. Error");
    return 1;
}

puts("Connected\n");
close(sock);
while(1);
return 0;
}

when I run server code and then client code it works fine but when I terminate client code run it again (server code executed once only) it automatically connects to server without accept being called by server.

I don't want client to get connected until server calls accept() to connect with client.

I just want client to wait or give some timeout until server calls accept() to establish connection between them.

Output I am getting is below :

Server Output:

root@beaglebone:/home/Saad/test# ./server_test
Socket created                                                      
bind done                              
Waiting for incoming connections...
Connection accepted
I am at While loop

Client Output:

root@beaglebone:/home/Saad/test# ./client_test     
Socket created                         
Connected                                                           

^C                                                   
root@beaglebone:/home/Saad/test# ./client_test
Socket created                                              
Connected          

I don't know why this is happening and how to resolve it.

UPDATE:

I have tried the answer below after some edits in client code I am facing same problem.

Client code:

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
   char buf[1];
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];
int ret;

//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
    printf("Could not create socket");
}
puts("Socket created");

server.sin_addr.s_addr = inet_addr("192.168.1.2");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );

//Connect to remote server
ret = connect(sock , (struct sockaddr *)&server , sizeof(server));
if (ret < 0)
{
    perror("connect failed. Error");
    return 1;
}
recv(sock, buf, 1, MSG_WAITFORONE);
printf("%s",buf);
puts("Connected\n");
close(sock);
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
    printf("Could not create socket");
}
puts("Socket created");
ret = connect(sock , (struct sockaddr *)&server , sizeof(server));
if (ret < 0)
{
    perror("connect failed. Error");
    return 1;
}
else
{
 puts("Connected\n");
}
while(1);
return 0;
}

Client output:

root@beaglebone:/home/Saad/test# ./client_test_1
Socket created
1Connected

Socket created
Connected

Upvotes: 2

Views: 7011

Answers (2)

user207421
user207421

Reputation: 311039

I don't want client to get connected until server calls accept() to connect with client.

Bad luck, that's not how TCP works. listen(socket_desc , 3) creates a backlog queue, using the second parameter as a hint as to its length, which will be ignored in this case as it is too small. The purpose of this queue is to hold connections that have been completed by TCP but not yet accepted by the server application. Typical sizes vary from 50 to 500 or more, depending on the platform.

I just want client to wait or give some timeout until server calls accept() to establish connection between them.

Unimplementable. Why do you think you need this?

I don't know why this is happening and how to resolve it.

You can't resolve it, except by a pointless extra send/recv as per @IshayPeled's answer. It isn't a problem that needs resolving. If you think otherwise please tell us why. Every other TCP application ever written works this way. What's different about yours?

Upvotes: 1

Ishay Peled
Ishay Peled

Reputation: 2868

@EJP explained it well, if you want to fix you issue, use this code:

Client:

#include<stdio.h> //printf
#include<string.h>    //strlen
#include<sys/socket.h>    //socket
#include<arpa/inet.h> //inet_addr

int main(int argc , char *argv[])
{
    char buf[1];
    int sock;
    struct sockaddr_in server;
    char message[1000] , server_reply[2000];
    int ret;

    //Create socket
    sock = socket(AF_INET , SOCK_STREAM , 0);
    if (sock == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_family = AF_INET;
    server.sin_port = htons( 8888 );

    //Connect to remote server
    ret = connect(sock , (struct sockaddr *)&server , sizeof(server));
    if (ret < 0)
    {
        perror("connect failed. Error");
        return 1;
    }
    recv(sock, buf, 1, MSG_WAITFORONE);

    puts("Connected\n");
    close(sock);
    while(1);
    return 0;
}

Server:

#include<stdio.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write   
int main(int argc , char *argv[])
{   
    int socket_desc , client_sock , c , read_size;
    struct sockaddr_in server , client;
    char client_message[2000];

    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8888 );

    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
        //print the error message
        perror("bind failed. Error");
        return 1;
    }
    puts("bind done");

    //Listen
    listen(socket_desc , 3);

    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);

    //accept connection from an incoming client
    client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);

    send(client_sock, "1", 1, 0);
    if (client_sock < 0)
    {
        perror("accept failed");
        return 1;
    }
    puts("Connection accepted");
    close(client_sock);
    puts("I am at While loop");
    while(1)
    {
    }
    return 0;
}

On the client side:
I added a recv call on the client side, that blocks until the server actually sends something.

On the server side:
I added a send call right after the accept call. That makes sure only clients that have been accepted will continue their code path.

Upvotes: 3

Related Questions