2017-02-22 5 views
-2

Я пытаюсь отправить данные с сервера клиенту всякий раз, когда клиент выполняет команду recv(). Поскольку код стоит прямо сейчас, я не могу заставить клиента печатать любые данные, которые он получает. Я не могу понять, что-то не так с моим сервером или клиентом, поэтому любая помощь будет оценена по достоинству. Благодаря!Отправка клиенту с сервера

client.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <netinet/ip.h> 


#define ECHO_PORT 9999 
#define BUF_SIZE 4096 

int main(int argc, char* argv[]) 
{ 
    if (argc != 3) 
    { 
     fprintf(stderr, "usage: %s <server-ip> <port>",argv[0]); 
     return EXIT_FAILURE; 
    } 

    char buf[BUF_SIZE]; 

    int status, sock, sock2; 
    struct addrinfo hints; 
    memset(&hints, 0, sizeof(struct addrinfo)); 
    struct addrinfo *servinfo; //will point to the results 
    hints.ai_family = AF_INET; //IPv4 
    hints.ai_socktype = SOCK_STREAM; //TCP stream sockets 
    hints.ai_flags = AI_PASSIVE; //fill in my IP for me 

    if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) 
    { 
     fprintf(stderr, "getaddrinfo error: %s \n", gai_strerror(status)); 
     return EXIT_FAILURE; 
    } 

    if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) 
    { 
     fprintf(stderr, "Socket failed"); 
     return EXIT_FAILURE; 
    } 

    if ((connect(sock, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0) 
    { 
     fprintf(stderr, "Connection failed"); 
     return EXIT_FAILURE; 
    } 

    if ((sock2 = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) 
    { 
     fprintf(stderr, "Socket failed"); 
     return EXIT_FAILURE; 
    } 

    if ((connect(sock2, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0) 
    { 
     fprintf(stderr, "Connection failed"); 
     return EXIT_FAILURE; 
    } 

    while (1) { 
     //char msg[BUF_SIZE] = "ashudfshuhafhu"; 
     //char msg[BUF_SIZE]; 
     //fgets(msg, BUF_SIZE, stdin); 
     //int i = 2; 
     //if (strlen(msg) == i) 
     // break; 
     int bytes_received; 
     // fprintf(stdout, "Sending %s", msg); 
     //send(sock, msg , strlen(msg), 0); 
     if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1) 
     { 
      buf[bytes_received] = '\0'; 
      fprintf(stdout, "Received %s", buf); 
     } 
    } 


    freeaddrinfo(servinfo); 
    close(sock);  
    return EXIT_SUCCESS; 

} 

Server.c

#include <netinet/in.h> 
#include <netinet/ip.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <unistd.h> 

#define ECHO_PORT 9999 
#define BUF_SIZE 4096 

int close_socket(int sock) 
{ 
     if (close(sock)) 
     { 
       fprintf(stderr, "Failed closing socket.\n"); 
       return 1; 
     } 
     return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    int sock, client_sock; 
    ssize_t readret; 
    socklen_t cli_size; 
    struct timeval tv; 
    struct sockaddr_in addr, cli_addr; 
    char buf[BUF_SIZE] = "wetwetwetwetwetwetwetwet"; 
    fd_set readfds, writefds; 
    fd_set activereadfds, activewritefds; 
    cli_size = sizeof(&cli_addr); 

    tv.tv_sec = 5; 
    tv.tv_usec = 0; 

    fprintf(stdout, "----- Echo Server -----\n"); 

    /* all networked programs must create a socket */ 
    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) 
    { 
      fprintf(stderr, "Failed creating socket.\n"); 
      return EXIT_FAILURE; 
    } 

    addr.sin_family = AF_INET; 
    addr.sin_port = htons(ECHO_PORT); 
    addr.sin_addr.s_addr = INADDR_ANY; 

    /* servers bind sockets to ports---notify the OS they accept connections */ 
    if (bind(sock, (struct sockaddr *) &addr, sizeof(addr))) 
    { 
      close_socket(sock); 
      fprintf(stderr, "Failed binding socket.\n"); 
      return EXIT_FAILURE; 
    } 


    if (listen(sock, 5)) 
    { 
      close_socket(sock); 
      fprintf(stderr, "Error listening on socket.\n"); 
      return EXIT_FAILURE; 
    } 

    FD_ZERO(&readfds); 
    FD_SET(sock, &activereadfds); 

    while (1) 
    { 
     fprintf(stdout,"in here.\n"); 
     readfds = activereadfds; 
     writefds = activewritefds; 
     FD_ZERO(&activereadfds); 
     FD_ZERO(&activewritefds); 

     if (select(51, &readfds, &writefds, NULL, &tv) < 0) 
     { 
      perror("select"); 
      return EXIT_FAILURE; 
     } 


     for (int i = 0; i < 10; ++i) 
     { 
      if (FD_ISSET (i, &readfds)) 
      { 
       if (i == sock) 
       { 
        fprintf(stdout, "main loop. \n"); 
        client_sock = accept(sock, 
           (struct sockaddr *) &cli_addr, &cli_size); 
        FD_SET(client_sock, &activereadfds); 
        FD_SET(client_sock, &activewritefds); 
        if (client_sock < 0) 
        { 
         perror("accept"); 
         return EXIT_FAILURE; 
        } 
       } else { 
         fprintf(stdout, "second loop \n"); 
         readret = send(i,buf, strlen(buf),0); 

         if (readret < 0) 
          fprintf(stdout, "yay"); 
         } 
       } 
      if (FD_ISSET(i, &writefds)) 
       { fprintf(stdout, "ugh \n"); 
        readret = send(i,buf,BUF_SIZE,0); 
        //if (readret > 0) 
        //while((readret = recv(i, buf, BUF_SIZE, 0)) >= 1) 
        // { 

           //if (send(i, buf, readret, 0) != readret) 
           //{ 
           // close_socket(i); 
           // close_socket(sock); 
           // fprintf(stderr, "Error sending to client.\n"); 
           // return EXIT_FAILURE; 
           //} 
       } 
      } 
     } 
    close_socket(sock); 

    return EXIT_SUCCESS; 
} 
+0

Что говорит отладчик, когда вы проходите через код? (И сколько смысла делает ваш код клиента, когда вы просто * читаете его?) –

+0

Код имеет смысл для меня, когда я его читаю, но это может быть потому, что я новичок в программировании сокетов. –

ответ

2
  1. Ваш сервер отправки только тогда, когда сокет готов для чтения , и как клиент никогда отправка, сервер тоже. Передача сервера должна произойти, когда клиентский сокет появляется в writefds, хотя на самом деле это неправильный способ использования этой функции. Действительно, вы должны просто отправить и только добавить и беспокоиться о writefds, если send() вызвал EAGAIN/EWOULDBLOCK.

  2. Вы могли бы получать необнаружения ошибки в клиенте:

    if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1) 
    { 
        buf[bytes_received] = '\0'; 
        fprintf(stdout, "Received %s", buf); 
    } 
    

    Это должно продолжаться:

    else if (bytes_received == 0) 
    { 
        fprintf(stdout, "peer disconnected\n"); 
        break; 
    } 
    else // < 0: error 
    { 
        fprintf(stdout, "recv() error %s\n", strerror(errno)); 
        break; 
    } 
    

    Вы должны напечатать фактические ошибки, как это всякий раз, когда вы получите сообщение об ошибке от системный вызов.

+0

Почему клиент должен отправлять сервер для отправки? –

+0

Я уже точно объяснил это, в первом абзаце. – EJP

+0

Я извиняюсь за недоразумение, но, я думаю, мне интересно, как сервер знает, когда отправлять в сокет, тем более, что не рекомендуется добавлять клиентский сокет в 'writefds' так, как я его сейчас. –

Смежные вопросы