简体   繁体   中英

Unix domain socket non-blocking operation failed at listen, in C

This program will calculate RTT for non blocking communication for simple IPC program using UNIX domain socket.

I'm having a problem with socket programming where at server-side my socket exit with error at listen() . The blocking version of the code works fine; I tried to modify it to non-blocking with SOCK_NONBLOCK at socket() , but it seems to fail at listening:

hafizul96@ubuntu:~/asyntest$ ./Server [SERVER PROCESS] Socket Created, Process ID : 7334 [SERVER PROCESS] Socket Listening.. [SERVER PROCESS] Error Accepting **

Client:

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

#define SERV_SOCK_PATH "ipc_unix_sock.server"
#define CLIN_SOCK_PATH "ipc_unix_sock.client"

void Array_Init(int *, int);
void Write_to_File(FILE *, int *, int);

int main(int argc, char *argv[])
{
    struct sockaddr_un serv_addr, cli_addr;
    int client_socket, add_len, rc, array_len, send_bytes, recv_bytes;
    pid_t process_id = getpid();
    clock_t start, end;
    double elapsed = 0.0;
    FILE *cli_arr_recv;
    FILE *cli_arr_send;
    char arr_len[10];
    int *Array_Buff;
    array_len = atoi(argv[1]);
    sprintf(arr_len, "%d", array_len);


    Array_Buff = malloc(sizeof(int)*array_len);
    cli_arr_send = fopen("cli_arr_send.txt","w+");
    cli_arr_recv = fopen("cli_arr_recv.txt","w+");

    memset(&serv_addr, 0, sizeof(struct sockaddr_un));
    memset(&cli_addr, 0, sizeof(struct sockaddr_un));
    memset(Array_Buff, 0, array_len);
    Array_Init(Array_Buff, array_len);
    //Copy arrays to file
    Write_to_File(cli_arr_send, Array_Buff, array_len);

//NON-BLOCKING SOCKET//
    if((client_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0))<0)
    {
        printf("[CLIENT PROCESS] Socket Creation Error\n");
        fclose(cli_arr_recv);
        fclose(cli_arr_send);
        close(client_socket);
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("[CLIENT PROCESS] Socket Created, Process ID :%d\n", process_id);
        printf("[CLIENT PROCESS] %lubytes Allocated\n", sizeof(int)*array_len);
    }

    cli_addr.sun_family = AF_UNIX;
    strcpy(cli_addr.sun_path, CLIN_SOCK_PATH);
    add_len = sizeof(cli_addr);

    unlink(CLIN_SOCK_PATH);
    if((rc = bind(client_socket, (struct sockaddr*)&cli_addr, add_len ))<0)
    {
        printf("[CLIENT PROCESS] Bind error \n");
        fclose(cli_arr_recv);
        fclose(cli_arr_send);
        close(client_socket);
        exit(EXIT_FAILURE);
    }

    serv_addr.sun_family = AF_UNIX;
    strcpy(serv_addr.sun_path, SERV_SOCK_PATH);
    if((rc = connect(client_socket, (struct sockaddr*)&serv_addr, add_len))<0)
    {
        printf("[CLIENT PROCESS] Failed to Connect to Server Process\n");
        fclose(cli_arr_recv);
        fclose(cli_arr_send);
        close(client_socket);
        exit(EXIT_FAILURE);
    }


    start = clock();
    if((rc = send(client_socket, arr_len, sizeof(arr_len), 0))<0)
    {
        printf("[CLIENT PROCESS] Failed to Send Array Len to Server Process");
        fclose(cli_arr_recv);
        fclose(cli_arr_send);
        close(client_socket);
        exit(EXIT_FAILURE);
    }

    if((send_bytes = send(client_socket, Array_Buff, sizeof(int)*array_len, 0))<0)
    {
        printf("[CLIENT PROCESS] Failed to Send Array Elements to Server Process");
        fclose(cli_arr_recv);
        fclose(cli_arr_send);
        close(client_socket);
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("[CLIENT PROCESS] Total Bytes Sent = %dbytes\n",send_bytes);
        memset(Array_Buff, 0, array_len); //reset buffer
        if((recv_bytes = recv(client_socket, Array_Buff, sizeof(int)*array_len, MSG_WAITALL))<0)
        {
            fclose(cli_arr_recv);
            fclose(cli_arr_send);
            close(client_socket);
            exit(EXIT_FAILURE);
        }
        else
        {
            //Finishes RTT
            end = clock();
            printf("[CLIENT PROCESS] Total Bytes Received Back = %dbytes\n",recv_bytes);
            Write_to_File(cli_arr_recv, Array_Buff, array_len);
        }

    }
    elapsed = (end - start)/(double)CLOCKS_PER_SEC;
    printf("[CLIENT PROCESS] RTT(Round Trip Time) is =  %fs\n", elapsed);
    printf("[CLIENT PROCESS] Program Completed.\n");

    free(Array_Buff);
    fclose(cli_arr_recv);
    fclose(cli_arr_send);
    close(client_socket);
    exit(EXIT_SUCCESS);
}
void Array_Init(int *Array_Buff, int array_len)
{
    unsigned int seed = 184611;
    srand(seed);
    for(int i = 0; i< array_len; i++)
    {
        *(Array_Buff++) = rand() % 999999;
    }
}
void Write_to_File(FILE *outfile, int *Array_Buff, int array_len)
{
    for(int i = 0; i<array_len; i++)
    {
        fprintf(outfile, " %d ", *(Array_Buff++));
    }
    printf("[CLIENT PROCESS] File Write Completed.. \n");
}

Server:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SERV_SOCK_PATH "ipc_unix_sock.server"

void Write_to_File(FILE *, int *, int);

int main(int argc, char *argv[])
{
    struct sockaddr_un serv_addr, cli_addr;
    int server_sock, client_sock, add_len, rc, array_len;
    int backlog = 2, recv_bytes = 0, send_bytes = 0;
    pid_t process_id = getpid();
    FILE *serv_file;
    int *Array_Buff;
    char arr_len[10];

    serv_file = fopen("serv_recv_arr.txt","w+");

    /*Making sure that address struct set to zero*/
    memset(&serv_addr, 0, sizeof(struct sockaddr_un));
    memset(&cli_addr, 0, sizeof(struct sockaddr_un));
    memset(arr_len, 0, 10);
//NON-BLOCKING SOCKET TYPE
    if((server_sock = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0 )
    {
        printf("[SERVER PROCESS] Error Socket\n");
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("[SERVER PROCESS] Socket Created, Process ID : %d\n", process_id);
    }

    serv_addr.sun_family = AF_UNIX;
    strcpy(serv_addr.sun_path, SERV_SOCK_PATH);
    add_len = sizeof(serv_addr);

    unlink(SERV_SOCK_PATH);
    if((rc = bind(server_sock, (struct sockaddr*)&serv_addr, add_len))<0)
    {
    printf("[SERVER PROCESS] Error Binding\n");
    close(server_sock);
    exit(EXIT_FAILURE);
    }

    if((rc = listen(server_sock, backlog)) <0 )
    {
        printf("[SERVER PROCESS] Error Listening\n");
        close(server_sock);
        fclose(serv_file);
        exit(EXIT_FAILURE);
    }

    printf("[SERVER PROCESS] Socket Listening..\n");

    if((client_sock = accept(server_sock, (struct sockaddr*)&client_sock, &add_len))<0)
    {
        printf("[SERVER PROCESS] Error Accepting\n");
        close(server_sock);
        close(client_sock);
        fclose(serv_file);
        exit(EXIT_FAILURE);
    }

    add_len = sizeof(cli_addr);
    if((rc = getpeername(client_sock, (struct sockaddr*)&cli_addr, &add_len))<0)
    {
        printf("[SERVER PROCESS] Error Getting Peername\n");
        close(server_sock);
        close(client_sock);
        fclose(serv_file);
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("[SERVER PROCESS] Client Socket Filepath = %s\n", cli_addr.sun_path);
    }

    printf("[SERVER PROCESS] Waiting to Recv Msg..\n");


    if((rc =  recv(client_sock, arr_len, sizeof(arr_len), MSG_WAITALL))<0)
    {
        printf("[SERVER PROCESS] Error Receiving Msg..\n");
        close(server_sock);
        close(client_sock);
        fclose(serv_file);
        exit(EXIT_FAILURE);
    }
    printf("[SERVER PROCESS] Array Len Received %s\n", arr_len);
    array_len = atoi(arr_len);
    Array_Buff = malloc(sizeof(int)*array_len);
    printf("[SERVER PROCESS] %lubytes Allocated\n", sizeof(int)*array_len);
    memset(Array_Buff, 0, array_len);

    if((recv_bytes = recv(client_sock, Array_Buff, sizeof(int)*array_len, MSG_WAITALL))<0)
    {
        printf("[SERVER PROCESS] Error Receiving Msg..\n");
        close(server_sock);
        close(client_sock);
        fclose(serv_file);
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("[SERVER PROCESS] Total Bytes Recv = %dbytes\n",recv_bytes);
        if((send_bytes = send(client_sock, Array_Buff, sizeof(int)*array_len, 0))<0)
        {
            printf("[SERVER PROCESS] Error Sending Back Array\n");
            close(server_sock);
            close(client_sock);
            fclose(serv_file);
            exit(EXIT_FAILURE);
        }
        else
        {
             printf("[SERVER PROCESS] Total Bytes Sent Back = %dbytes\n", send_bytes);
        }

    }
    Write_to_File(serv_file, Array_Buff, array_len);
    printf("[SERVER PROCESS] Program Completed.\n");

    free(Array_Buff);
    close(server_sock);
    close(client_sock);
    exit(EXIT_SUCCESS);
}

void Write_to_File(FILE *outfile, int *Array_Buff, int array_len)
{
    for(int i = 0; i<array_len; i++)
    {
        fprintf(outfile, " %d ", *(Array_Buff++));
    }
    printf("[SERVER PROCESS] File Write Completed.. \n");
    fclose(outfile);
}

Does anybody know what the problem is and how to fix it?

Because your socket is non-blocking, accept does not wait until a connection happens but it returns EAGAIN or EWOULDBLOCK value. You shall call accept repeatedly until it returns a different value. To avoid consuming 100% of your CPU by those calls, do some sleep between two calls or use select or poll to wait until your socket is readable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM