TCP服务器没有等待客户端响应?

时间:2018-05-14 19:45:53

标签: c sockets tcp

我已经完成了使用C语言中的TCP套接字编程编写轮盘游戏的任务。

代码工作正常,直到我接近完成它,并且出于某种未知原因,它停止正常工作,我无法追踪错误。

用于处理简单recv()调用的代码,因此我尝试制作readn()函数(实际上是从另一篇文章中获取),但它没有解决问题。

我可能会忽略这个问题,它位于for (int i = 0 ; i < max_round ; i++)函数的main()循环中。

这是我的服务器:

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

int
readn(int f, void *av, int n)
{
    char *a;
    int m, t;

    a = av;
    t = 0;
    while(t < n){
        m = read(f, a+t, n-t);
        if(m <= 0){
            if(t == 0)
                return m;
            break;
        }
        t += m;
    }
    return t;
}

typedef struct
{
    int _count, _bet, _client, _currency;
    int _numbers[3];
    char *_color;
} Roulette;

int find_element(int searched, int numbers[], int count)
{
    for (int i = 0; i < count; i++)
    {
        if (searched == numbers[i])
            return 1;
    }
    return 0;
}

void Round_Results(Roulette *obj1, Roulette *obj2, const int size)
{
    char *lose_msg = "Sajnos nem nyert ebben a korben!\n";
    char *win_msg = "Gratulalok, ebben a korben nyert!\n";
    char answer[size];

    srand(time(NULL));
    int winner_number = rand() % 10;
    if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 0) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 0))
    {
        send(obj1->_client, lose_msg, size, 0);
        obj1->_currency = obj1->_currency - obj1->_bet;
        printf("%d", obj1->_currency);
        sprintf(answer, "%d", obj1->_currency);
        send(obj1->_client, answer, size, 0);

        send(obj2->_client, lose_msg, size, 0);
        obj2->_currency = obj2->_currency - obj2->_bet;
        printf("%d", obj2->_currency);
        sprintf(answer, "%d", obj2->_currency);
        send(obj2->_client, answer, size, 0);
    }
    else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 1) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 0))
    {
        send(obj1->_client, win_msg, size, 0);
        obj1->_currency = obj1->_currency + obj1->_bet * (6 / obj1->_count);
        printf("%d", obj1->_currency);
        sprintf(answer, "%d", obj1->_currency);
        send(obj1->_client, answer, size, 0);

        send(obj2->_client, lose_msg, size, 0);
        obj2->_currency = obj2->_currency - obj2->_bet;
        printf("%d", obj2->_currency);
        sprintf(answer, "%d", obj2->_currency);
        send(obj2->_client, answer, size, 0);
    }
    else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 0) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 1))
    {
        send(obj1->_client, lose_msg, size, 0);
        obj1->_currency = obj1->_currency - obj1->_bet;
        printf("%d", obj1->_currency);
        sprintf(answer, "%d", obj1->_currency);
        send(obj1->_client, answer, size, 0);

        send(obj2->_client, win_msg, size, 0);
        obj2->_currency = obj2->_currency + obj2->_bet * (6 / obj2->_count);
        printf("%d", obj2->_currency);
        sprintf(answer, "%d", obj2->_currency);
        send(obj2->_client, answer, size, 0);
    }
    else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 1) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 1))
    {
        send(obj1->_client, win_msg, size, 0);
        obj1->_currency = obj1->_currency + obj1->_bet * (6 / obj1->_count);
        printf("%d", obj2->_currency);
        sprintf(answer, "%d", obj2->_currency);
        send(obj1->_client, answer, size, 0);

        send(obj2->_client, win_msg, size, 0);
        obj2->_currency = obj2->_currency + obj2->_bet * (6 / obj1->_count);
        printf("%d", obj2->_currency);
        sprintf(answer, "%d", obj2->_currency);
        send(obj2->_client, answer, size, 0);
    }
}

void Initialize(int client, int count, int numbers[], int bet, char *color, Roulette *obj)
{
    obj->_client = client;
    obj->_count = count;
    obj->_color = color;
    obj->_bet = bet;

    for (int i = 0; i < count; i++)
        obj->_numbers[i] = numbers[i];
}

void Round_Information(int client, const int size, Roulette *obj)
{
    char *message = malloc(size);
    char *money_msg = "Mennyi zsetonba fogad?\n";
    char *number_msg = "Melyik szamra fogad?\n[0-9]\n";
    char *count_msg = "Mennyi szamra fogad?\n[1-3]\n";
    char *color_msg = "Milyen szinre fogad?\n[black/red]\n";
    int count = 0;

    char *color;
    int numbers[3];
    int bet;

    //Bet
    send(client, money_msg, size, 0);
    readn(client,message,size);
    bet = atoi(message);

    //Count
    send(client, count_msg, size, 0);
    readn(client,message,size);
    count = atoi(message);

    //Number/Numbers
    for (int i = 0; i < count; i++)
    {
        send(client, number_msg, size, 0);
        readn(client,message,size);
        numbers[i] = atoi(message);
    }

    //Color
    send(client, color_msg, size, 0);
    readn(client,message,size);
    color = message;

    Initialize(client, count, numbers, bet, color, obj);

    free(message);
    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("tul keves argumentum!\nusage : ./valami PORT_NR\n");
        exit(-1);
    }

    const int size = 50;
    int max_round, starting_money;
    int flag = 0;
    int on = 1;
    char *message = malloc(size);
    char *round_msg = "Korok szama :\n";
    char *greeting_msg = "Sikeresen csatlakozott a szerverre!\n";
    char *waiting_msg = "A masik jatekosra varunk!\n";
    char *win_msg = "Gratulalok !\nMegnyerte a jatekot!\n";
    char *lose_msg = "Jatek vege !\nSajnos nem nyert!\n";
    Roulette *obj1 = malloc(size);
    Roulette *obj2 = malloc(size);

    int server_socket = socket(AF_INET, SOCK_STREAM, flag);
    if (server_socket < 0)
    {
        printf("Nem sikerult a socket-et letrehozni\n");
        exit(-1);
    }

    struct sockaddr_in server_adress;
    server_adress.sin_addr.s_addr = INADDR_ANY;
    server_adress.sin_family = AF_INET;
    server_adress.sin_port = atoi(argv[1]);

    setsockopt(server_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

    int binding_server = bind(server_socket, (struct sockaddr *)&server_adress, sizeof(server_adress));
    if (binding_server < 0)
    {
        printf("nem sikerult bindolni a szervert!\n");
        exit(-1);
    }

    listen(server_socket, 2);

    int client1 = accept(server_socket, NULL, NULL);
    int client2 = accept(server_socket, NULL, NULL);

    send(client1, greeting_msg, size, flag);
    send(client2, greeting_msg, size, flag);

    printf("Milyen hosszu legyen a jatek ? (Hany kor)\n");
    scanf("%s", message);
    max_round = atoi(message);

    //Korok szama
    send(client1, message, size, flag);
    send(client2, message, size, flag);

    printf("Mennyi zsetonnal kezdodjon a jatek?\n");
    scanf("%s", message);
    starting_money = atoi(message);

    //Kezdo penz
    send(client1, message, size, flag);
    send(client2, message, size, flag);

    obj1->_currency = starting_money;
    obj2->_currency = starting_money;

    for (int i = 0; i < max_round; i++)
    {
        Round_Information(client1, size, obj1);
        Round_Information(client2, size, obj2);
        Round_Results(obj1, obj2, size);                                    
    }

    if (obj1->_currency > obj2->_currency)
    {
        send(obj1->_client, win_msg, size, flag);
        send(obj2->_client, lose_msg, size, flag);
    }
    else if (obj1->_currency < obj2->_currency)
    {
        send(obj2->_client, win_msg, size, flag);
        send(obj1->_client, lose_msg, size, flag);
    }
    else
    {
        send(obj1->_client, lose_msg, size, flag);
        send(obj2->_client, lose_msg, size, flag);
    }

    close(client1);
    close(client2);
    close(server_socket);
    free(message);
    free(obj1);
    free(obj2);
    return 0;
}

以下是客户:

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

void Round_Information(int client, const int size, int currency)
{
    char *message = malloc(size);
    char answer[size];
    char *black = "black";
    char *red = "red";
    int count = 0;
    memset(answer, 0, size);

    //Bet
    recv(client, message, size, 0);
    if (currency == 0)
    {
        printf("Game over!\nVeszitett!\n");
        close(client);
    }
    while (atoi(answer) < 1 || atoi(answer) > currency)
    {
        if (strcmp(answer, "befejeztem"))
        {
            close(client);
        }
        printf("%s", message);
        scanf("%s", answer);
    }
    if (strcmp(answer, "befejeztem"))
    {
        close(client);
    }
    send(client, answer, size, 0);
    answer[0] = '0';

    //Count
    recv(client, message, size, 0);
    while (atoi(answer) < 1 || atoi(answer) > 3)
    {
        if (strcmp(answer, "befejeztem"))
        {
            close(client);
        }
        printf("%s", message);
        scanf("%s", answer);
    }
    count = atoi(answer);
    if (strcmp(answer, "befejeztem"))
    {
        close(client);
    }
    send(client, answer, size, 0);

    //Number/Numbers
    for (int i = 0; i < count; i++)
    {
        recv(client, message, size, 0);
        answer[0] = 'z';
        while (atoi(answer) <= 0 || atoi(answer) > 9)
        {
            if (strcmp(answer, "befejeztem"))
            {
                close(client);
            }
            printf("%s", message);
            scanf("%s", answer);
        }
        if (strcmp(answer, "befejeztem"))
        {
            close(client);
        }
        send(client, answer, size, 0);
    }

    //Color
    recv(client, message, size, 0);
    while ((strcmp(answer, black) != 0) && (strcmp(answer, red) != 0))
    {
        if (strcmp(answer, "befejeztem"))
        {
            close(client);
        }
        printf("%s", message);
        scanf("%s", answer);
    }
    if (strcmp(answer, "befejeztem"))
    {
        close(client);
    }
    send(client, answer, size, 0);
    free(message);
}

void Round_Results(int client_socket, char *message, const int size, int *currency)
{
    recv(client_socket, message, size, 0);
    printf("%s\n", message);
    recv(client_socket, message, size, 0);
    (*currency) = atoi(message);
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("tul keves argumentum!\nusage : ./valami PORT_NR\n");
        exit(-1);
    }

    const int size = 50;
    int flag = 0;
    int max_round, currency;
    int on = 1;
    char message[size];

    int client_socket = socket(AF_INET, SOCK_STREAM, flag);
    if (client_socket < 0)
    {
        printf("Nem sikerult a socketet letrehozni!\n");
        exit(-1);
    }

    struct sockaddr_in server_adress;
    server_adress.sin_addr.s_addr = INADDR_ANY;
    server_adress.sin_family = AF_INET;
    server_adress.sin_port = atoi(argv[1]);

    setsockopt(client_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
    setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));

    int connection = connect(client_socket, (struct sockaddr *)&server_adress, sizeof(server_adress));
    if (connection < 0)
    {
        printf("Nem sikerult kapcsolodni a szerverhez!\n");
        exit(-1);
    }

    //Sikeres kapcsolodas
    int receive = recv(client_socket, message, size, flag);
    if (receive < 0)
    {
        printf("Nem sikerult megkapni az uzenetet!\n");
        exit(-1);
    }
    printf("%s", message);

    //Korok szama
    receive = recv(client_socket, message, size, flag);
    if (receive < 0)
    {
        printf("Nem sikerult megkapni az uzenetet!\n");
        exit(-1);
    }
    printf("Korok szama :%s\n", message);
    max_round = atoi(message);

    //Kezdo penz
    receive = recv(client_socket, message, size, flag);
    if (receive < 0)
    {
        printf("Nem sikerult megkapni az uzenetet!\n");
        exit(-1);
    }
    printf("Jelenlegi zsetonok mennyisege :%s\n", message);
    currency = atoi(message);

    for (int i = 0; i < max_round; i++)
    {
        Round_Information(client_socket, size, currency);
        Round_Results(client_socket, message, size, &currency);
        printf("Jelenlegi zseton :%d\n", currency);
    }

    recv(client_socket, message, size, flag);
    printf("%s\n", message);
    close(client_socket);

    return 0;
}

1 个答案:

答案 0 :(得分:0)

这不容易阅读,因为我不知道输出是什么意思,但我认为我找到了你的问题。

if (strcmp(answer, "befejeztem"))
    {
        close(client);
    }
当字符串相等时,

strcmp为0。这意味着几乎在每种情况下都会关闭套接字。实际上在第一个循环中,答案为零表示您正在关闭套接字。如果您关闭套接字但服务器尝试发送数据,程序将收到SIGPIPE信号,我认为默认处理程序将中止该程序。

尝试将所有这些if语句更改为:

if(!strcmp(answer, "befejeztem"))
{
    close(client);
}