【问题标题】:server can't send message to Client over Socket in C服务器无法通过 C 中的 Socket 向客户端发送消息
【发布时间】:2015-04-12 12:08:38
【问题描述】:

您好,我正在编写 2 个程序(服务器、客户端),它们应该通过套接字相互通信。客户端能够毫无问题地将其第一条消息发送到服务器,但是当服务器尝试应答时,客户端只收到一个空消息:recv(...) 为 0。 调用send(...) 函数后服务器突然停止。 这是我的代码:

服务器:

    /* Create a new TCP/IP socket `sockfd`, and set the SO_REUSEADDR
       option for this socket. Then bind the socket to localhost:portno,
       listen, and wait for new connections, which should be assigned to
       `connfd`. Terminate the program in case of an error.
    */
    struct sockaddr_in sin,
                    peer_addr;
    //-----gen socket-----//
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        bail_out(EXIT_PARITY_ERROR, "could not create Socket");

    //-----bind-----//
    memset(&sin, 0, sizeof (sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(options.portno);
    sin.sin_addr.s_addr = INADDR_ANY;
    if (bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0)
        bail_out(EXIT_PARITY_ERROR, "Failed to bind to Port");

    //-----listen-----//
    if (listen(sockfd, 5) < 0)
        bail_out(EXIT_PARITY_ERROR, "Server can't accepted connection");

    //-----accept-----//
    int sock_len = sizeof peer_addr;
    if ((connfd = accept(sockfd, (struct sockaddr*)&peer_addr, (socklen_t *)&sock_len)) < 0) //fragen
        bail_out(EXIT_PARITY_ERROR, "Can't accept connection to Client");
    /* accepted the connection */

   //Some other Code which has nothing to do with my Error!

    /* read from client (WORKS FINE!!)*/
    if (read_from_client(connfd, &buffer[0], READ_BYTES) == NULL) {
        if (quit) break; /* caught signal */
            bail_out(EXIT_FAILURE, "read_from_client");
    }
    request = (buffer[1] << 8) | buffer[0];
    DEBUG("Round %d: Received 0x%x\n", round, request);

    /* compute answer */
    correct_guesses = compute_answer(request, buffer, options.secret);
    if (round == MAX_TRIES && correct_guesses != SLOTS) {
        buffer[0] |= 1 << GAME_LOST_ERR_BIT;
    }

    DEBUG("Sending byte 0x%x\n", buffer[0]);


    /* send message to client */
    if (send_to_client(sockfd, &buffer[0], WRITE_BYTES) == NULL) { //Error in this Method!
        if (quit) break; /* caught signal */
            bail_out(EXIT_FAILURE, "can't send message!");
    }

方法:

static uint8_t *send_to_client(int fd, uint8_t *buffer, size_t n)
{
    /* loop, as packet can arrive in several partial reads */
    size_t bytes_send = 0;
    do {
        ssize_t r = send(fd, buffer + bytes_send, n - bytes_send, 0); //Program stops HERE!
        printf("%d\n", (int)r); //This and the following lines will not be executed!
        if (r <= 0) {
            return NULL;
        }
        bytes_send += r;
    } while (bytes_send < n);

    if (bytes_send < n) {
        return NULL;
    }
    return buffer;
}

客户:(可能有用)

sockfd = cnt_to_server(argv[1], argv[2]);
uint8_t buffer;
uint16_t msg_buffer;
    do
    {
        msg_buffer = generate_msg(&msg);
        printf("Sending byte 0x%x\n", msg_buffer);
        if (send_to_server(sockfd, &msg_buffer, WRITE_BYTES) == NULL) //works
            error_exit(EXIT_FAILURE, "can't send message!");
        if (read_from_server(sockfd, &buffer, READ_BYTES) == NULL) //NULL
            error_exit(EXIT_FAILURE, "can't read message!");
        printf("received byte 0x%x\n", buffer);
    } while (game_continue(buffer, &msg));

    (void)close(sockfd);

方法:

uint8_t* read_from_server(int fd, uint8_t *buffer, int n)
{
    /* loop, as packet can arrive in several partial reads */
    size_t bytes_recv = 0;
    do {
        ssize_t r;
        r = recv(fd, buffer + bytes_recv, n - bytes_recv, 0); //0
        printf("%d\n", (int)r);
        if (r <= 0) {
            return NULL;
        }
        bytes_recv += r;
    } while (bytes_recv < n);

    if (bytes_recv < n) {
        return NULL;
    }
    return buffer;
}

int cnt_to_server(const char *par_server, const char *par_port)
{
    struct sockaddr_in server;
    struct hostent *hp;

    int  sockfd;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        error_exit(EXIT_FAILURE, "could not create Socket");

    server.sin_family = AF_INET;

    if ((hp = gethostbyname(par_server)) == 0)
        error_exit(EXIT_FAILURE, "host error!");

    memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
    server.sin_port = htons(parse_port(par_port));

    if (connect(sockfd, (struct sockaddr*) &server, sizeof server) < 0)
        error_exit(EXIT_FAILURE, "could not connect!");

    return sockfd;
}

谢谢你帮我解决这个问题!

【问题讨论】:

  • 你能展示一下如何打开两端的套接字吗?
  • @MarioTheSpoon 完成!
  • WRITE_BYTES 和 READ_BYTES 的值是否正确?
  • 确定:客户:#define READ_BYTES (2)#define WRITE_BYTES (1)
  • connfd not sockfd in call to send...

标签: c sockets pointers server


【解决方案1】:

改变

if (send_to_client(sockfd, &buffer[0], WRITE_BYTES) == NULL)

if (send_to_client(connfd, &buffer[0], WRITE_BYTES) == NULL)

【讨论】:

    【解决方案2】:

    解决方案是使用connfd(连接套接字的文件描述符)而不是sockfd

        /* read from client */
        if (read_from_client(connfd, &buffer[0], READ_BYTES) == NULL) {
            if (quit) break; /* caught signal */
                bail_out(EXIT_FAILURE, "read_from_client");
        }
    

    【讨论】:

      猜你喜欢
      • 2023-04-03
      • 2020-05-25
      • 2015-04-25
      • 2013-11-10
      • 2011-05-12
      • 1970-01-01
      • 2017-05-15
      • 1970-01-01
      相关资源
      最近更新 更多