2015-03-27 6 views
1

Я пишу простую клиентскую серверную программу с использованием сокетов домена unix, но у меня возникают проблемы с вызовом recv() в моей клиентской программе.unix socket send() успешно завершен, но recv() не удается

Программа выполняет следующие:

  • Сервер устанавливает сокет и ожидает соединения
  • Клиент подключается и Посылает строку
  • Сервер принимает строку и отправляет строку обратно клиенту (подобный эхо)
  • Client RECV() вызов не выполняется, возвращая "ресурс временно недоступен"
  • Клиент выходит
  • Сервер ждет другого подключения

Я также попытался использовать вызов poll() в моем клиенте, чтобы дождаться ответа с сервера. В этом случае, однако, вызов recv() просто получает 0, подразумевая, что соединение было закрыто сервером, которого у него нет.

Я исчерпал Google эту ошибку, но никаких исправлений, которые я пришел, похоже, применимы к моему коду.

Я включил моего клиента (с кодом опроса() и кодом сервера ниже.

У меня, вероятно, отсутствует что-то очевидное ... но любое понимание было бы оценено по достоинству!

Серверный код:

/* 
* testServer.c 
* 
*/ 

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include <termios.h> 
#include <fcntl.h> 
#include <poll.h> 
#include <signal.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdbool.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <sys/un.h> 
#include <linux/spi/spidev.h> 
#include <linux/sockios.h> 
#include <errno.h> 

#define SOCK_PATH "/var/run/ts.serv" 

void handleSockIO(int *sockDesc); 

int main() 
{ 
    int sock; 
    struct sockaddr_un sock_addr; 
    int len, p; 
    struct pollfd poll_fd[1]; 

    printf("[TS] testServer Started.\r\n"); 

    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 
    { 
     perror("[TS]wr_sock creation"); 
    } 
    else 
    { 
     printf("[TS] Created socket descriptor.\r\n"); 
    } 


    sock_addr.sun_family = AF_UNIX; 
    strcpy(sock_addr.sun_path, SOCK_PATH); 
    unlink(sock_addr.sun_path); 

    len = strlen(sock_addr.sun_path) + sizeof(sock_addr.sun_family); 

    if (bind(sock, (struct sockaddr *)&sock_addr, len) == -1) 
    { 
     perror("[TS]sock bind failed\r\n"); 
    } 
    else 
    { 
     printf("[TS] Bound socket to sock_addr.\r\n"); 
    } 

    if (listen(sock, 5) == -1) 
    { 
     perror("[TS] sock listen fail"); 
    } 
    else 
    { 
     printf("[TS] Socket now listening.\r\n"); 
    } 

    poll_fd[0].fd = sock; 
    poll_fd[0].events = POLLIN; 

    printf("[TS] Waiting for a connection...\r\n"); 

    while (1) 
    { 
     p = poll(poll_fd, 1, 1); //Wait for 1 ms for data 

     if (p == -1) 
     { 
      perror("[TS] Poll"); 
     } 
     else if (p == 0) 
     { 
      //printf("Timeout occurred!\n"); 
     } 
     else 
     { 
      if (poll_fd[0].revents & POLLIN)//Data available to read without blocking 
      { 
       printf("[TS] Data available on sock..\r\n"); 
       handleSockIO(&sock); 

       printf("[TS] Waiting for another connection...\r\n"); 
      } 
     } 
    }//While(1) 

    return 0; 
} 

void handleSockIO(int *sockDesc) 
{ 
    int ioSock, n; 
    socklen_t t; 
    struct sockaddr_un remote_addr; 
    char str[15]; 

    memset(str, ' ', sizeof(str)); 

    t = sizeof(remote_addr); 

    if ((ioSock = accept(*sockDesc, (struct sockaddr *)&remote_addr, &t)) == -1) 
    { 
     perror("accept failed\r\n"); 
    } 
    else 
    { 
     printf("[TS] Receiving...\r\n"); 

     n = recv(ioSock, str, sizeof(str), 0); 

     if (n < 0) 
      printf("[TS] recvfrom failed: %s\r\n", strerror(errno)); 
     else if(n == 0) 
     { 
      printf("[TS] Received %d on ioSock...\r\n", n); 
     } 
     else if(n > 0) 
     { 
      printf("[TS] Received: %s, which is %d long.\r\n", str, strlen(str)); 

      printf("[TS] Echoing response...\r\n"); 

      if (send(ioSock, str, n, 0) == -1) //Echo str back 
      { 
       printf("[TS] send failed: %s\r\n", strerror(errno)); 
      } 
      else 
      { 
       printf("[TS] Send successful\r\n"); 
      } 

      //============Wait to close IO descriptor================= 
      int r; 
      char temp[1]; //Arbitrary buffer to satisfy recv() 
      do 
      { 
       printf("[TS] Waiting for client to close connection...\r\n"); 
       r = recv(ioSock, temp, sizeof(temp), 0); 

       if (r == 0) 
       { 
        printf("[TS] Client closed connection, closing ioSock...\r\n"); 
        close(ioSock); 
       } 
      } while (r != 0); 

      //======================================================== 
     }//if(n>0) else... 
    }  
} 

код клиента:

/* 
* testClient.c 
* 
*/ 

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include <termios.h> 
#include <fcntl.h> 
#include <poll.h> 
#include <signal.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdbool.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <sys/un.h> 
#include <linux/sockios.h> 
#include <errno.h> 

#define CHAR_BUF_SIZE 15 
#define SEND_STRING "Hello!" 
#define SOCK_PATH "/var/run/ts.serv" 

int main() 
{ 
    char str[CHAR_BUF_SIZE] = {0}; 
    int c, len, n, p; 
    int s; // s will hold a socket descriptor returned by socket() 
    struct sockaddr_un serv_addr; 
    struct pollfd poll_fd[1]; 

    printf("[TC] testClient Started.\r\n"); 

    //===============SOCKET SETUP=============================== 

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 
    { 
     printf("[TC] Socket failed: %s\r\n", strerror(errno)); 
    } 

    memset(&serv_addr, '0', sizeof(serv_addr)); 

    serv_addr.sun_family = AF_UNIX; 
    strcpy(serv_addr.sun_path, SOCK_PATH); 

    len = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); 

    //========================================================== 

    // printf("[TC]Trying to connect to TS socket...\r\n"); 

    //===============RESPONSE POLL SETUP======================== 

    poll_fd[0].fd = s; 
    poll_fd[0].events = POLLIN; 

    //========================================================== 

    printf("[TC] Connecting to SOCK_PATH...\r\n"); 

    c = connect(s, (struct sockaddr *)&serv_addr, len); 

    if (c == -1) 
    { 
     printf("[TC] Connection failed: %s\r\n", strerror(errno)); 
    } 
    else 
    { 
     printf("[TC] Connected. Sending string....\r\n"); 

     if (send(s, SEND_STRING, strlen(SEND_STRING), 0) == -1) 
     { 
      printf("[TC] send() failed: %s\r\n", strerror(errno)); 
     } 
     else 
     { 
      printf("[TC] Send on SOCK_PATH successful.\r\n"); 
      //Sending complete------------------------------------------------ 
      //Wait for response... 

      printf("[TC] Waiting for server response...\r\n"); 

//   p = poll(poll_fd, 1, -1); //Wait for a response 
//   
//   if (p == -1) 
//   { 
//    perror("[TC] Poll"); 
//   } 
//   else 
//   { 
//    if(poll_fd[0].revents & POLLIN) 
//    { 
        n = recv(s, str, sizeof(str), 0); 

        if (n < 0) 
        { 
         printf("[TC] Receive on SOCK_PATH failed: %s\r\n", 
           strerror(errno)); 
        } 
        else if(n == 0) 
        { 
         printf("[TC] %d Received on SOCK_PATH.\r\n", n); 
        } 
        else if(n > 0) 
        { 
         printf("[TC] Received %d from SOCK_PATH: %s\r\n", 
           n, str); 
        } 
//    } 
//   } 
     }//if(send()) 
    }//if(connect()) 

    printf("[TC] Transction complete, closing connection and exiting.\r\n"); 

    close(s); 

    return 0; 
} 
+0

'unsigned int t' должно быть' socklen_t t'. – alk

+0

Измените все параметры 'strlen (x)' в 'recv()' вызовы 'sizeof x', заменив' x' по необходимости в каждом случае. Нет смысла измерять длину строки, которую вы еще не получили, или предварительно заполнить буфер приема, чтобы вы могли это сделать. Перед закрытием сокета нет необходимости блокировать в 'recv()'. – EJP

+1

Есть много ошибок, таких как 'len = strlen (serv_addr.sun_path) + sizeof (serv_addr.sun_family);' вместо 'len = sizeof (serv_addr)' ' –

ответ

0

len = sizeof(serv_addr) вместо len = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family) должен решать вам проблему. Также не игнорируйте предупреждения компилятора, скажем n = recv(s, str, strlen(str), 0), где n объявлено как int и ssize_t, возвращаемое recv. Это поможет вам избежать будущих ошибок.

+0

Спасибо за ответ. И это не вызвало никаких предупреждений компилятора на моем ручном устройстве, было вполне счастливо присвоить возвращаемое значение recv для int без литья. – cSmout

+0

Добро пожаловать , любой способ, ssize_t/size_t/etc может отличаться от одной ОС/платформы к другой. –