Странное поведение в простом приложении клиент-сервер обратного отсчета C - PullRequest
2 голосов
/ 18 декабря 2011

Я пытаюсь реализовать простое приложение обратного отсчета в C с использованием сокетов UDP. У меня очень странная проблема с серверной частью приложения: оно должно получить номер от клиента, а затем отправить разные номера для обратного отсчета. Так, если, например, пользователь вводит 5 на клиенте, то сервер должен получить 5 и отправить 4, 3, 2, 1 и 0 клиенту. Вот мой код:

#define BUFFERSIZE 512
#define PORT 55123

void ClearWinSock()
{
    #if defined WIN32
        WSACleanup();
    #endif
}

int main()
{
    #if defined WIN32

    WSADATA wsaData;
    WORD wVersionRequested;

    wVersionRequested = MAKEWORD(2, 2);

    if(WSAStartup(wVersionRequested, &wsaData) != 0)
    {
        printf("Error: unable to initialize the socket!\n");
        return -1;
    }

    #endif

    int mainSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

    if(mainSocket < 0)
    {
        printf( "Error: unable to create the socket!\n");
        ClearWinSock();
        return -1;
    }

    struct sockaddr_in serverSockAddrIn;
    memset(&serverSockAddrIn, 0, sizeof(serverSockAddrIn));
    serverSockAddrIn.sin_family = AF_INET;
    serverSockAddrIn.sin_port = htons(PORT);
    serverSockAddrIn.sin_addr.s_addr = inet_addr("127.0.0.1");

    if(bind(mainSocket, (struct sockaddr*) &serverSockAddrIn, sizeof(serverSockAddrIn)) < 0)
    {
        fprintf(stderr, "Error: unable to bind the socket!\n");
        ClearWinSock();
        return -1;
    }

    char buffer[BUFFERSIZE];

    struct sockaddr_in clientAddress;
    unsigned int clientAddressLength;
    int recvMessageSize;

    while(1)
    {
        clientAddressLength = sizeof(clientAddress);

        recvMessageSize = recvfrom(mainSocket, buffer, BUFFERSIZE, 0, (struct sockaddr*) &clientAddress, &clientAddressLength);

        int countdownValue;

        sscanf(buffer, "%d", &countdownValue);

        printf("\nNumber received: %d\n", countdownValue);

        int index;

        for(index = countdownValue - 1; index >= 0; --index)
        {
            itoa(index, buffer, 10);

            int outputStringLength = strlen(buffer);

            if(sendto(mainSocket, buffer, outputStringLength, 0, (struct sockaddr*) &clientAddress, sizeof(clientAddress))  != outputStringLength)
            {
                printf("Error: unable to send the message!");
            }
        }
    }

    ClearWinSock();
    return 0;
}

Теперь проблема в том, что если я, например, отправляю номер 5 от клиента, иногда сервер работает правильно, а иногда он говорит «Число получено: 5», ничего не отправляет, а затем говорит «Номер получен : 0 "в течение 5 раз.

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

1 Ответ

0 голосов
/ 19 декабря 2011

Ваш клиент и ваш сервер одновременно прослушивают один и тот же порт? Если это так, вы можете рассмотреть возможность их прослушивания на разных портах (например, клиент отправляет на X и прослушивает порт Y; сервер отправляет на порт Y и прослушивает порт X), чтобы они не мешали друг другу или случайно не принимали их собственные отправленные пакеты, когда клиент и сервер работают на одном хосте.

В качестве альтернативы, вы можете указать клиенту и серверу использовать один и тот же порт, всегда выполняя следующий код перед вызовом bind ():

  const int trueValue = 1;
  setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &trueValue, sizeof(trueValue));
...