Тестовый код UDP не получает сообщения (C ++)

0

Во-первых, прошу прощения за беспорядок. Я пытаюсь изменить пример UDP-кода для работы через windows/linux. Вероятно, есть несколько следов кода, зависящего от окна, все еще лежащего вокруг, где я пытался понять, что на самом деле происходит неправильно.

Это мой первый опыт работы с UDP вместо TCP.

Если я раскомментирую материал recvfrom в клиенте, он блокирует неопределенный IFF сервер. В противном случае он возвращается немедленно, как и ожидалось. Я не могу понять, почему мой сервер, в его текущем состоянии, не может ничего получить от клиента.

Что мне здесь не хватает?

Кстати, я должен также упомянуть, что если я свяжу сокет для serverAddress с клиентом и попытаюсь позволить ему получать от себя (вообще не оставляя сервер), у него нет никаких проблем с этим. (Кроме того, я еще не пробовал эту версию на linux.)

благодаря

Сервер (ресивер):

#ifdef _WIN32 || _WIN64 || _WINDOWS_
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define __COMPILE_FOR_WINDOWS__
#define SOCKET_INVALID(s) (s==INVALID_SOCKET)
#define SOCKET_TYPE SOCKET
#endif
#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET_INVALID(s) (s<0)
#define SOCKET_TYPE int
#endif

#include <iostream>

#define BUFFER_LENGTH  1024

int main(int argc, char** argv)
{

#ifdef __COMPILE_FOR_WINDOWS__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
    {
        std::cerr << "could not start up winsock-2.2\n";
        return 1;
    }
#endif 

    struct sockaddr_in serverAddress,
        clientAddress;
    unsigned short Port = 27015;
    char RecvBuf[BUFFER_LENGTH];

    SOCKET_TYPE socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/* or 0? */);
    if (SOCKET_INVALID(socketHandle))
    {
        std::cerr << "could not make socket\n";
        return 1;
    }

    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(Port);
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(socketHandle, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) != 0)
    {
        std::cerr << "could not bind socket\n";
        return 1;
    }

    int len;
    int client_addr_len;// = sizeof(clientAddress);
    while (1)
    {
        len = recvfrom(socketHandle,RecvBuf,BUFFER_LENGTH,0,(struct sockaddr*)&clientAddress,&client_addr_len);
        if (strncmp(RecvBuf,"END",3)==0) 
            break;
        if (len > 0)
        {
            //sendto(socketHandle, RecvBuf, len, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
            RecvBuf[len] = 0;
            std::cout << "received: " << RecvBuf << std::endl;
        }
    }

#ifdef __COMPILE_FOR_WINDOWS__
    closesocket(socketHandle);
    WSACleanup();
#endif
#ifdef linux
    close(socketHandle);
#endif
    std::cout<< "done\n";
    return 0;
}

#ifdef __COMPILE_FOR_WINDOWS__
#undef __COMPILE_FOR_WINDOWS__
#endif

#undef BUFFER_LENGTH
#undef SOCKET_INVALID

#ifdef SOCKET_TYPE
#undef SOCKET_TYPE
#endif

Клиент (отправитель):

#ifdef _WIN32 || _WIN64 || _WINDOWS_
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define __COMPILE_FOR_WINDOWS__
#define SOCKET_INVALID(s) (s==INVALID_SOCKET)
#define SOCKET_TYPE SOCKET
#endif
#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET_INVALID(s) (s<0)
#define SOCKET_TYPE int
#endif

#include <iostream>

#define BUFFER_LENGTH  1024

int main(int argc, char** argv)
{

#ifdef __COMPILE_FOR_WINDOWS__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
    {
        std::cerr << "could not start up winsock-2.2\n";
        return 1;
    }
#endif 

    struct sockaddr_in serverAddress,
        clientAddress;
    unsigned short Port = 27015;
    char msgBuf[BUFFER_LENGTH];

    SOCKET_TYPE socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/* or 0? */);
    if (SOCKET_INVALID(socketHandle))
    {
        std::cerr << "could not make socket\n";
        return 1;
    }

    //char address[512];
    //std::cout << "enter ip: ";
    //std::cin.getline(address, 512);

    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(Port);
    serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");

    int len;
    std::cout << "gimme something: ";
    std::cin.getline(msgBuf, BUFFER_LENGTH);

    while (1)
    {
        int n = sendto(socketHandle,msgBuf, strlen(msgBuf), 0,(struct sockaddr*)&serverAddress, sizeof(serverAddress));
        std::cout << "sent "<<n<<" bytes of the msg\n";
        /*len = recvfrom(socketHandle,msgBuf,BUFFER_LENGTH, 0, NULL, NULL);
        if (len > 0)
        {
            msgBuf[len] = 0;
            fputs(msgBuf, stdout);
        }else if(len < 0)std::cerr << "windowsy error\n";*/
    }

#ifdef __COMPILE_FOR_WINDOWS__
    closesocket(socketHandle);
    WSACleanup();
#endif
#ifdef linux
    close(socketHandle);
#endif
    std::cout << "done\n";
    return 0;
}

#ifdef __COMPILE_FOR_WINDOWS__
#undef __COMPILE_FOR_WINDOWS__
#endif

#undef BUFFER_LENGTH
#undef SOCKET_INVALID

#ifdef SOCKET_TYPE
#undef SOCKET_TYPE
#endif
Теги:
sockets
udp

2 ответа

0
Лучший ответ

Нашел проблему! Мне пришлось раскомментировать часть для client_addr_len = sizeof (clientAddress) ;.

По какой-то причине я думал, что переменная больше похожа на то, что она была предназначена для получения длины для адресов различного размера из функции recvfrom(), поэтому я сомневался, что она действительно нуждалась в начальном значении. Это был единственный способ заставить летательные аппараты начать летать. :П

Кроме того, для любых будущих читателей проблема socklen_t может быть быстро исправлена путем добавления

typedef int socklen_t;

к окну определенного раздела верхних директив и изменению int len; to socklen_t len; - сказал Гунтрам.

1

Я не видел никаких ошибок, поэтому я скомпилировал обе программы на своей машине (openSuSE 11.3). Единственное, что мне пришлось изменить, это int client_addr_len to socklen_t client_addr_len Связь работала немедленно. (Конечно, клиент столкнулся с бесконечным циклом while(1)).

Вы делаете это на одной машине или на 2? Клиент всегда отправляет на localhost, поэтому не работают две разные машины. Есть ли блокировка брандмауэра?

Попробуйте сделать "netstat -au | grep 27015 'до и после запуска сервера. Случается ли что-нибудь еще в этом сокете перед запуском сервера? Слушает ли сервер после его запуска?

Попробуйте запустить клиент и сервер с помощью strace. Вы видите ошибки системного вызова?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню